mirror of
https://github.com/containers/podman.git
synced 2025-05-17 15:18:43 +08:00
podman5 machine reconfig 1
this is a logical place to get changes upstream before they grow out of control. this pr is the first in an effort to deduplicate machine code and streamline code flow. a lot of code is simply moved to eliminate circular imports. names and specific paths can ultimately be changed. i dont like some of the descriptive interface names, etc. ultimately, i think once we have the "old" code sanitized, we can re-use some of those. clearly some of what is in here is temporary and will either be deleted, changed, or moved again as this effort comes to a close. right now, the machine code does not use any of the "new" code. you will see in `init` and `rm` some commented out code that hooks it. i'm afraid things will get worse before they get better (way worse). [NO NEW TESTS NEEDED] Signed-off-by: Brent Baude <bbaude@redhat.com>
This commit is contained in:
@ -26,7 +26,7 @@ var (
|
||||
ValidArgsFunction: completion.AutocompleteNone,
|
||||
}
|
||||
|
||||
initOpts = machine.InitOptions{}
|
||||
initOpts = define.InitOptions{}
|
||||
initOptionalFlags = InitOptionalFlags{}
|
||||
defaultMachineName = machine.DefaultMachineName
|
||||
now bool
|
||||
@ -187,6 +187,20 @@ func initMachine(cmd *cobra.Command, args []string) error {
|
||||
// Finished = *, err != nil - Exit with an error message
|
||||
return err
|
||||
}
|
||||
|
||||
// The following is for enabling podman machine approach
|
||||
/*
|
||||
s := new(p5qemu.QEMUStubber)
|
||||
mc, err := p5.Init(initOpts, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO callback needed for the configuration file
|
||||
if err := mc.Write(); err != nil {
|
||||
return err
|
||||
}
|
||||
*/
|
||||
newMachineEvent(events.Init, events.Event{Name: initOpts.Name})
|
||||
fmt.Println("Machine init complete")
|
||||
|
||||
|
@ -64,6 +64,15 @@ func list(cmd *cobra.Command, args []string) error {
|
||||
err error
|
||||
)
|
||||
|
||||
// Podman 5 development
|
||||
/*
|
||||
s := new(p5qemu.QEMUStubber)
|
||||
if err := p5.List([]vmconfigs.VMStubber{s}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
listResponse, err = provider.List(opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("listing vms: %w", err)
|
||||
|
2
go.mod
2
go.mod
@ -29,6 +29,7 @@ require (
|
||||
github.com/docker/go-connections v0.5.0
|
||||
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651
|
||||
github.com/docker/go-units v0.5.0
|
||||
github.com/go-openapi/errors v0.21.0
|
||||
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466
|
||||
github.com/google/gofuzz v1.2.0
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
@ -119,7 +120,6 @@ require (
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-openapi/analysis v0.21.4 // indirect
|
||||
github.com/go-openapi/errors v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/loads v0.21.2 // indirect
|
||||
|
@ -112,7 +112,7 @@ func (v AppleHVVirtualization) LoadVMByName(name string) (machine.VM, error) {
|
||||
return m.loadFromFile()
|
||||
}
|
||||
|
||||
func (v AppleHVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM, error) {
|
||||
func (v AppleHVVirtualization) NewMachine(opts define.InitOptions) (machine.VM, error) {
|
||||
m := MacMachine{Name: opts.Name}
|
||||
|
||||
if len(opts.USBs) > 0 {
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/applehv/vfkit"
|
||||
"github.com/containers/podman/v4/pkg/machine/connection"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/pkg/machine/ignition"
|
||||
"github.com/containers/podman/v4/pkg/machine/sockets"
|
||||
@ -129,7 +130,7 @@ func (m *MacMachine) setVfkitInfo(cfg *config.Config, readySocket define.VMFile)
|
||||
|
||||
// addMountsToVM converts the volumes passed through the CLI to virtio-fs mounts
|
||||
// and adds them to the machine
|
||||
func (m *MacMachine) addMountsToVM(opts machine.InitOptions, virtiofsMnts *[]machine.VirtIoFs) error {
|
||||
func (m *MacMachine) addMountsToVM(opts define.InitOptions, virtiofsMnts *[]machine.VirtIoFs) error {
|
||||
var mounts []vmconfigs.Mount
|
||||
for _, volume := range opts.Volumes {
|
||||
source, target, _, readOnly, err := machine.ParseVolumeFromPath(volume)
|
||||
@ -145,7 +146,7 @@ func (m *MacMachine) addMountsToVM(opts machine.InitOptions, virtiofsMnts *[]mac
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MacMachine) Init(opts machine.InitOptions) (bool, error) {
|
||||
func (m *MacMachine) Init(opts define.InitOptions) (bool, error) {
|
||||
var (
|
||||
key string
|
||||
virtiofsMnts []machine.VirtIoFs
|
||||
@ -225,7 +226,7 @@ func (m *MacMachine) Init(opts machine.InitOptions) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
err = machine.AddSSHConnectionsToPodmanSocket(
|
||||
err = connection.AddSSHConnectionsToPodmanSocket(
|
||||
m.UID,
|
||||
m.Port,
|
||||
m.IdentityPath,
|
||||
@ -294,7 +295,7 @@ func (m *MacMachine) Init(opts machine.InitOptions) (bool, error) {
|
||||
}
|
||||
|
||||
func (m *MacMachine) removeSystemConnections() error {
|
||||
return machine.RemoveConnections(m.Name, fmt.Sprintf("%s-root", m.Name))
|
||||
return connection.RemoveConnections(m.Name, fmt.Sprintf("%s-root", m.Name))
|
||||
}
|
||||
|
||||
func (m *MacMachine) Inspect() (*machine.InspectInfo, error) {
|
||||
@ -385,7 +386,7 @@ func (m *MacMachine) Remove(name string, opts machine.RemoveOptions) (string, fu
|
||||
|
||||
confirmationMessage += "\n"
|
||||
return confirmationMessage, func() error {
|
||||
machine.RemoveFilesAndConnections(files, m.Name, m.Name+"-root")
|
||||
connection.RemoveFilesAndConnections(files, m.Name, m.Name+"-root")
|
||||
// TODO We will need something like this for applehv too i think
|
||||
/*
|
||||
// Remove the HVSOCK for networking
|
||||
|
@ -22,36 +22,14 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type InitOptions struct {
|
||||
CPUS uint64
|
||||
DiskSize uint64
|
||||
IgnitionPath string
|
||||
ImagePath string
|
||||
Volumes []string
|
||||
VolumeDriver string
|
||||
IsDefault bool
|
||||
Memory uint64
|
||||
Name string
|
||||
TimeZone string
|
||||
URI url.URL
|
||||
Username string
|
||||
ReExec bool
|
||||
Rootful bool
|
||||
UID string // uid of the user that called machine
|
||||
UserModeNetworking *bool // nil = use backend/system default, false = disable, true = enable
|
||||
USBs []string
|
||||
}
|
||||
|
||||
const (
|
||||
DefaultMachineName string = "podman-machine-default"
|
||||
apiUpTimeout = 20 * time.Second
|
||||
)
|
||||
|
||||
type RemoteConnectionType string
|
||||
|
||||
var (
|
||||
SSHRemoteConnection RemoteConnectionType = "ssh"
|
||||
ForwarderBinaryName = "gvproxy"
|
||||
DefaultIgnitionUserName = "core"
|
||||
ForwarderBinaryName = "gvproxy"
|
||||
)
|
||||
|
||||
type Download struct {
|
||||
@ -120,7 +98,7 @@ type RemoveOptions struct {
|
||||
type InspectOptions struct{}
|
||||
|
||||
type VM interface {
|
||||
Init(opts InitOptions) (bool, error)
|
||||
Init(opts define.InitOptions) (bool, error)
|
||||
Inspect() (*InspectInfo, error)
|
||||
Remove(name string, opts RemoveOptions) (string, func() error, error)
|
||||
Set(name string, opts SetOptions) ([]error, error)
|
||||
@ -130,24 +108,6 @@ type VM interface {
|
||||
Stop(name string, opts StopOptions) error
|
||||
}
|
||||
|
||||
func GetLock(name string, vmtype define.VMType) (*lockfile.LockFile, error) {
|
||||
// FIXME: there's a painful amount of `GetConfDir` calls scattered
|
||||
// across the code base. This should be done once and stored
|
||||
// somewhere instead.
|
||||
vmConfigDir, err := GetConfDir(vmtype)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lockPath := filepath.Join(vmConfigDir, name+".lock")
|
||||
lock, err := lockfile.GetLockFile(lockPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating lockfile for VM: %w", err)
|
||||
}
|
||||
|
||||
return lock, nil
|
||||
}
|
||||
|
||||
type DistributionDownload interface {
|
||||
HasUsableCache() (bool, error)
|
||||
Get() *Download
|
||||
@ -167,26 +127,6 @@ type InspectInfo struct {
|
||||
Rootful bool
|
||||
}
|
||||
|
||||
func (rc RemoteConnectionType) MakeSSHURL(host, path, port, userName string) url.URL {
|
||||
// TODO Should this function have input verification?
|
||||
userInfo := url.User(userName)
|
||||
uri := url.URL{
|
||||
Scheme: "ssh",
|
||||
Opaque: "",
|
||||
User: userInfo,
|
||||
Host: host,
|
||||
Path: path,
|
||||
RawPath: "",
|
||||
ForceQuery: false,
|
||||
RawQuery: "",
|
||||
Fragment: "",
|
||||
}
|
||||
if len(port) > 0 {
|
||||
uri.Host = net.JoinHostPort(uri.Hostname(), port)
|
||||
}
|
||||
return uri
|
||||
}
|
||||
|
||||
// GetCacheDir returns the dir where VM images are downloaded into when pulled
|
||||
func GetCacheDir(vmType define.VMType) (string, error) {
|
||||
dataDir, err := GetDataDir(vmType)
|
||||
@ -226,6 +166,26 @@ func GetGlobalDataDir() (string, error) {
|
||||
return dataDir, os.MkdirAll(dataDir, 0755)
|
||||
}
|
||||
|
||||
func GetMachineDirs(vmType define.VMType) (*define.MachineDirs, error) {
|
||||
rtDir, err := getRuntimeDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rtDir = filepath.Join(rtDir, "podman")
|
||||
configDir, err := GetConfDir(vmType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dataDir, err := GetDataDir(vmType)
|
||||
dirs := define.MachineDirs{
|
||||
ConfigDir: configDir,
|
||||
DataDir: dataDir,
|
||||
RuntimeDir: rtDir,
|
||||
}
|
||||
return &dirs, err
|
||||
}
|
||||
|
||||
// DataDirPrefix returns the path prefix for all machine data files
|
||||
func DataDirPrefix() (string, error) {
|
||||
data, err := homedir.GetDataHome()
|
||||
@ -307,7 +267,7 @@ type VirtProvider interface { //nolint:interfacebloat
|
||||
IsValidVMName(name string) (bool, error)
|
||||
List(opts ListOptions) ([]*ListResponse, error)
|
||||
LoadVMByName(name string) (VM, error)
|
||||
NewMachine(opts InitOptions) (VM, error)
|
||||
NewMachine(opts define.InitOptions) (VM, error)
|
||||
NewDownload(vmName string) (Download, error)
|
||||
RemoveAndCleanMachines() error
|
||||
VMType() define.VMType
|
||||
@ -465,3 +425,22 @@ func (dl Download) AcquireVMImage(imagePath string) (*define.VMFile, FCOSStream,
|
||||
}
|
||||
return imageLocation, fcosStream, nil
|
||||
}
|
||||
|
||||
// Deprecated: GetLock
|
||||
func GetLock(name string, vmtype define.VMType) (*lockfile.LockFile, error) {
|
||||
// FIXME: there's a painful amount of `GetConfDir` calls scattered
|
||||
// across the code base. This should be done once and stored
|
||||
// somewhere instead.
|
||||
vmConfigDir, err := GetConfDir(vmtype)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lockPath := filepath.Join(vmConfigDir, name+".lock")
|
||||
lock, err := lockfile.GetLockFile(lockPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating lockfile for VM: %w", err)
|
||||
}
|
||||
|
||||
return lock, nil
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/containers/podman/v4/pkg/machine/connection"
|
||||
)
|
||||
|
||||
func TestRemoteConnectionType_MakeSSHURL(t *testing.T) {
|
||||
@ -27,7 +28,7 @@ func TestRemoteConnectionType_MakeSSHURL(t *testing.T) {
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
rc RemoteConnectionType
|
||||
rc connection.RemoteConnectionType
|
||||
args args
|
||||
want url.URL
|
||||
}{
|
||||
|
36
pkg/machine/connection/add.go
Normal file
36
pkg/machine/connection/add.go
Normal file
@ -0,0 +1,36 @@
|
||||
package connection
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
)
|
||||
|
||||
// AddSSHConnectionsToPodmanSocket adds SSH connections to the podman socket if
|
||||
// no ignition path is provided
|
||||
func AddSSHConnectionsToPodmanSocket(uid, port int, identityPath, name, remoteUsername string, opts define.InitOptions) error {
|
||||
if len(opts.IgnitionPath) > 0 {
|
||||
fmt.Println("An ignition path was provided. No SSH connection was added to Podman")
|
||||
return nil
|
||||
}
|
||||
uri := SSHRemoteConnection.MakeSSHURL(LocalhostIP, fmt.Sprintf("/run/user/%d/podman/podman.sock", uid), strconv.Itoa(port), remoteUsername)
|
||||
uriRoot := SSHRemoteConnection.MakeSSHURL(LocalhostIP, "/run/podman/podman.sock", strconv.Itoa(port), "root")
|
||||
|
||||
uris := []url.URL{uri, uriRoot}
|
||||
names := []string{name, name + "-root"}
|
||||
|
||||
// The first connection defined when connections is empty will become the default
|
||||
// regardless of IsDefault, so order according to rootful
|
||||
if opts.Rootful {
|
||||
uris[0], names[0], uris[1], names[1] = uris[1], names[1], uris[0], names[0]
|
||||
}
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
if err := AddConnection(&uris[i], names[i], identityPath, opts.IsDefault && i == 0); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
//go:build amd64 || arm64
|
||||
|
||||
package machine
|
||||
package connection
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/containers/common/pkg/config"
|
||||
@ -105,3 +107,28 @@ func RemoveFilesAndConnections(files []string, names ...string) {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
type RemoteConnectionType string
|
||||
|
||||
var SSHRemoteConnection RemoteConnectionType = "ssh"
|
||||
|
||||
// MakeSSHURL
|
||||
func (rc RemoteConnectionType) MakeSSHURL(host, path, port, userName string) url.URL {
|
||||
// TODO Should this function have input verification?
|
||||
userInfo := url.User(userName)
|
||||
uri := url.URL{
|
||||
Scheme: "ssh",
|
||||
Opaque: "",
|
||||
User: userInfo,
|
||||
Host: host,
|
||||
Path: path,
|
||||
RawPath: "",
|
||||
ForceQuery: false,
|
||||
RawQuery: "",
|
||||
Fragment: "",
|
||||
}
|
||||
if len(port) > 0 {
|
||||
uri.Host = net.JoinHostPort(uri.Hostname(), port)
|
||||
}
|
||||
return uri
|
||||
}
|
@ -1,4 +1,21 @@
|
||||
package define
|
||||
|
||||
import "os"
|
||||
|
||||
const UserCertsTargetPath = "/etc/containers/certs.d"
|
||||
const DefaultIdentityName = "machine"
|
||||
|
||||
var (
|
||||
DefaultFilePerm os.FileMode = 0644
|
||||
)
|
||||
|
||||
type CreateVMOpts struct {
|
||||
Name string
|
||||
Dirs *MachineDirs
|
||||
}
|
||||
|
||||
type MachineDirs struct {
|
||||
ConfigDir string
|
||||
DataDir string
|
||||
RuntimeDir string
|
||||
}
|
||||
|
23
pkg/machine/define/initopts.go
Normal file
23
pkg/machine/define/initopts.go
Normal file
@ -0,0 +1,23 @@
|
||||
package define
|
||||
|
||||
import "net/url"
|
||||
|
||||
type InitOptions struct {
|
||||
CPUS uint64
|
||||
DiskSize uint64
|
||||
IgnitionPath string
|
||||
ImagePath string
|
||||
Volumes []string
|
||||
VolumeDriver string
|
||||
IsDefault bool
|
||||
Memory uint64
|
||||
Name string
|
||||
TimeZone string
|
||||
URI url.URL
|
||||
Username string
|
||||
ReExec bool
|
||||
Rootful bool
|
||||
UID string // uid of the user that called machine
|
||||
UserModeNetworking *bool // nil = use backend/system default, false = disable, true = enable
|
||||
USBs []string
|
||||
}
|
@ -116,7 +116,7 @@ func (v HyperVVirtualization) LoadVMByName(name string) (machine.VM, error) {
|
||||
return m.loadFromFile()
|
||||
}
|
||||
|
||||
func (v HyperVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM, error) {
|
||||
func (v HyperVVirtualization) NewMachine(opts define.InitOptions) (machine.VM, error) {
|
||||
m := HyperVMachine{Name: opts.Name}
|
||||
if len(opts.ImagePath) < 1 {
|
||||
return nil, errors.New("must define --image-path for hyperv support")
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
||||
"github.com/containers/libhvee/pkg/hypervctl"
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/connection"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/pkg/machine/hyperv/vsock"
|
||||
"github.com/containers/podman/v4/pkg/machine/ignition"
|
||||
@ -129,7 +130,7 @@ func (m *HyperVMachine) readAndSplitIgnition() error {
|
||||
return vm.SplitAndAddIgnition("ignition.config.", reader)
|
||||
}
|
||||
|
||||
func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) {
|
||||
func (m *HyperVMachine) Init(opts define.InitOptions) (bool, error) {
|
||||
var (
|
||||
key string
|
||||
err error
|
||||
@ -192,7 +193,7 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) {
|
||||
m.Port = sshPort
|
||||
|
||||
m.RemoteUsername = opts.Username
|
||||
err = machine.AddSSHConnectionsToPodmanSocket(
|
||||
err = connection.AddSSHConnectionsToPodmanSocket(
|
||||
m.UID,
|
||||
m.Port,
|
||||
m.IdentityPath,
|
||||
@ -315,7 +316,7 @@ func (m *HyperVMachine) unregisterMachine() error {
|
||||
}
|
||||
|
||||
func (m *HyperVMachine) removeSystemConnections() error {
|
||||
return machine.RemoveConnections(m.Name, fmt.Sprintf("%s-root", m.Name))
|
||||
return connection.RemoveConnections(m.Name, fmt.Sprintf("%s-root", m.Name))
|
||||
}
|
||||
|
||||
func (m *HyperVMachine) Inspect() (*machine.InspectInfo, error) {
|
||||
@ -441,7 +442,7 @@ func (m *HyperVMachine) Remove(_ string, opts machine.RemoveOptions) (string, fu
|
||||
|
||||
confirmationMessage += "\n"
|
||||
return confirmationMessage, func() error {
|
||||
machine.RemoveFilesAndConnections(files, m.Name, m.Name+"-root")
|
||||
connection.RemoveFilesAndConnections(files, m.Name, m.Name+"-root")
|
||||
m.removeNetworkAndReadySocketsFromRegistry()
|
||||
if err := vm.Remove(""); err != nil {
|
||||
return fmt.Errorf("removing virtual machine: %w", err)
|
||||
|
17
pkg/machine/lock/lock.go
Normal file
17
pkg/machine/lock/lock.go
Normal file
@ -0,0 +1,17 @@
|
||||
package lock
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/storage/pkg/lockfile"
|
||||
)
|
||||
|
||||
func GetMachineLock(name string, machineConfigDir string) (*lockfile.LockFile, error) {
|
||||
lockPath := filepath.Join(machineConfigDir, name+".lock")
|
||||
lock, err := lockfile.GetLockFile(lockPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating lockfile for VM: %w", err)
|
||||
}
|
||||
return lock, nil
|
||||
}
|
@ -5,10 +5,9 @@ package machine
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine/connection"
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
)
|
||||
|
||||
@ -30,33 +29,6 @@ func GetDevNullFiles() (*os.File, *os.File, error) {
|
||||
return dnr, dnw, nil
|
||||
}
|
||||
|
||||
// AddSSHConnectionsToPodmanSocket adds SSH connections to the podman socket if
|
||||
// no ignition path is provided
|
||||
func AddSSHConnectionsToPodmanSocket(uid, port int, identityPath, name, remoteUsername string, opts InitOptions) error {
|
||||
if len(opts.IgnitionPath) > 0 {
|
||||
fmt.Println("An ignition path was provided. No SSH connection was added to Podman")
|
||||
return nil
|
||||
}
|
||||
uri := SSHRemoteConnection.MakeSSHURL(LocalhostIP, fmt.Sprintf("/run/user/%d/podman/podman.sock", uid), strconv.Itoa(port), remoteUsername)
|
||||
uriRoot := SSHRemoteConnection.MakeSSHURL(LocalhostIP, "/run/podman/podman.sock", strconv.Itoa(port), "root")
|
||||
|
||||
uris := []url.URL{uri, uriRoot}
|
||||
names := []string{name, name + "-root"}
|
||||
|
||||
// The first connection defined when connections is empty will become the default
|
||||
// regardless of IsDefault, so order according to rootful
|
||||
if opts.Rootful {
|
||||
uris[0], names[0], uris[1], names[1] = uris[1], names[1], uris[0], names[0]
|
||||
}
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
if err := AddConnection(&uris[i], names[i], identityPath, opts.IsDefault && i == 0); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitAPIAndPrintInfo prints info about the machine and does a ping test on the
|
||||
// API socket
|
||||
func WaitAPIAndPrintInfo(forwardState APIForwardingState, name, helper, forwardSock string, noInfo, isIncompatible, rootful bool) {
|
||||
@ -158,7 +130,7 @@ following command in your terminal session:
|
||||
// SetRootful modifies the machine's default connection to be either rootful or
|
||||
// rootless
|
||||
func SetRootful(rootful bool, name, rootfulName string) error {
|
||||
return UpdateConnectionIfDefault(rootful, name, rootfulName)
|
||||
return connection.UpdateConnectionIfDefault(rootful, name, rootfulName)
|
||||
}
|
||||
|
||||
// WriteConfig writes the machine's JSON config file
|
||||
|
11
pkg/machine/options_darwin.go
Normal file
11
pkg/machine/options_darwin.go
Normal file
@ -0,0 +1,11 @@
|
||||
package machine
|
||||
|
||||
import "os"
|
||||
|
||||
func getRuntimeDir() (string, error) {
|
||||
tmpDir, ok := os.LookupEnv("TMPDIR")
|
||||
if !ok {
|
||||
tmpDir = "/tmp"
|
||||
}
|
||||
return tmpDir, nil
|
||||
}
|
11
pkg/machine/options_freebsd.go
Normal file
11
pkg/machine/options_freebsd.go
Normal file
@ -0,0 +1,11 @@
|
||||
package machine
|
||||
|
||||
import "os"
|
||||
|
||||
func getRuntimeDir() (string, error) {
|
||||
tmpDir, ok := os.LookupEnv("TMPDIR")
|
||||
if !ok {
|
||||
tmpDir = "/tmp"
|
||||
}
|
||||
return tmpDir, nil
|
||||
}
|
13
pkg/machine/options_linux.go
Normal file
13
pkg/machine/options_linux.go
Normal file
@ -0,0 +1,13 @@
|
||||
package machine
|
||||
|
||||
import (
|
||||
"github.com/containers/podman/v4/pkg/rootless"
|
||||
"github.com/containers/podman/v4/pkg/util"
|
||||
)
|
||||
|
||||
func getRuntimeDir() (string, error) {
|
||||
if !rootless.IsRootless() {
|
||||
return "/run", nil
|
||||
}
|
||||
return util.GetRootlessRuntimeDir()
|
||||
}
|
11
pkg/machine/options_windows.go
Normal file
11
pkg/machine/options_windows.go
Normal file
@ -0,0 +1,11 @@
|
||||
package machine
|
||||
|
||||
import "os"
|
||||
|
||||
func getRuntimeDir() (string, error) {
|
||||
tmpDir, ok := os.LookupEnv("TEMP")
|
||||
if !ok {
|
||||
tmpDir = os.Getenv("LOCALAPPDATA") + "\\Temp"
|
||||
}
|
||||
return tmpDir, nil
|
||||
}
|
134
pkg/machine/p5/host.go
Normal file
134
pkg/machine/p5/host.go
Normal file
@ -0,0 +1,134 @@
|
||||
package p5
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"maps"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
machineDefine "github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/pkg/machine/ocipull"
|
||||
"github.com/containers/podman/v4/pkg/machine/vmconfigs"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
/*
|
||||
Host
|
||||
├ Info
|
||||
├ OS Apply
|
||||
├ SSH
|
||||
├ List
|
||||
├ Init
|
||||
├ VMExists
|
||||
├ CheckExclusiveActiveVM *HyperV/WSL need to check their hypervisors as well
|
||||
*/
|
||||
|
||||
func Info() {}
|
||||
func OSApply() {}
|
||||
func SSH() {}
|
||||
|
||||
// List is done at the host level to allow for a *possible* future where
|
||||
// more than one provider is used
|
||||
func List(vmstubbers []vmconfigs.VMStubber) error {
|
||||
mcs, err := getMCs(vmstubbers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("machines")
|
||||
for name, mc := range mcs {
|
||||
logrus.Debugf("found machine -> %q %q", name, mc.Created)
|
||||
}
|
||||
fmt.Println("machines end")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Init(opts machineDefine.InitOptions, mp vmconfigs.VMStubber) (*vmconfigs.MachineConfig, error) {
|
||||
dirs, err := machine.GetMachineDirs(mp.VMType())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println("/// begin init")
|
||||
|
||||
mc, err := vmconfigs.NewMachineConfig(opts, dirs.ConfigDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
createOpts := machineDefine.CreateVMOpts{
|
||||
Name: opts.Name,
|
||||
Dirs: dirs,
|
||||
}
|
||||
|
||||
// Get Image
|
||||
// TODO This needs rework bigtime; my preference is most of below of not living in here.
|
||||
versionedOCIDownload, err := ocipull.NewVersioned(context.Background(), dirs.DataDir, opts.Name, mp.VMType().String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := versionedOCIDownload.Pull(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
unpacked, err := versionedOCIDownload.Unpack()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
logrus.Debugf("cleaning up %q", unpacked.GetPath())
|
||||
if err := unpacked.Delete(); err != nil {
|
||||
logrus.Errorf("unable to delete local compressed file %q:%v", unpacked.GetPath(), err)
|
||||
}
|
||||
}()
|
||||
imagePath, err := versionedOCIDownload.Decompress(unpacked)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mc.ImagePath = imagePath
|
||||
|
||||
// TODO needs callback to remove image
|
||||
|
||||
logrus.Debugf("--> imagePath is %q", imagePath.GetPath())
|
||||
// TODO development only -- set to qemu provider
|
||||
if err := mp.CreateVM(createOpts, mc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err := json.MarshalIndent(mc, "", " ")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println(string(b))
|
||||
fmt.Println("/// end init")
|
||||
return mc, nil
|
||||
}
|
||||
|
||||
// VMExists looks across given providers for a machine's existence. returns the actual config and found bool
|
||||
func VMExists(name string, vmstubbers []vmconfigs.VMStubber) (*vmconfigs.MachineConfig, bool, error) {
|
||||
mcs, err := getMCs(vmstubbers)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
mc, found := mcs[name]
|
||||
return mc, found, nil
|
||||
}
|
||||
|
||||
func CheckExclusiveActiveVM() {}
|
||||
|
||||
func getMCs(vmstubbers []vmconfigs.VMStubber) (map[string]*vmconfigs.MachineConfig, error) {
|
||||
mcs := make(map[string]*vmconfigs.MachineConfig)
|
||||
for _, stubber := range vmstubbers {
|
||||
dirs, err := machine.GetMachineDirs(stubber.VMType())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stubberMCs, err := vmconfigs.LoadMachinesInDir(dirs.ConfigDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
maps.Copy(mcs, stubberMCs)
|
||||
}
|
||||
return mcs, nil
|
||||
}
|
@ -2,7 +2,9 @@ package command
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
@ -14,6 +16,12 @@ import (
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
)
|
||||
|
||||
// defaultQMPTimeout is the timeout duration for the
|
||||
// qmp monitor interactions.
|
||||
var (
|
||||
defaultQMPTimeout = 2 * time.Second
|
||||
)
|
||||
|
||||
// QemuCmd is an alias around a string slice to prevent the need to migrate the
|
||||
// MachineVM struct due to changes
|
||||
type QemuCmd []string
|
||||
@ -234,3 +242,22 @@ type Monitor struct {
|
||||
// Timeout in seconds for qmp monitor transactions
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
// NewQMPMonitor creates the monitor subsection of our vm
|
||||
func NewQMPMonitor(name, machineRuntimeDir string) (Monitor, error) {
|
||||
if _, err := os.Stat(machineRuntimeDir); errors.Is(err, fs.ErrNotExist) {
|
||||
if err := os.MkdirAll(machineRuntimeDir, 0755); err != nil {
|
||||
return Monitor{}, err
|
||||
}
|
||||
}
|
||||
address, err := define.NewMachineFile(filepath.Join(machineRuntimeDir, "qmp_"+name+".sock"), nil)
|
||||
if err != nil {
|
||||
return Monitor{}, err
|
||||
}
|
||||
monitor := Monitor{
|
||||
Network: "unix",
|
||||
Address: *address,
|
||||
Timeout: defaultQMPTimeout,
|
||||
}
|
||||
return monitor, nil
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine/vmconfigs"
|
||||
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/compression"
|
||||
@ -16,7 +18,6 @@ import (
|
||||
"github.com/containers/podman/v4/pkg/machine/ignition"
|
||||
"github.com/containers/podman/v4/pkg/machine/qemu/command"
|
||||
"github.com/containers/podman/v4/pkg/machine/sockets"
|
||||
"github.com/containers/podman/v4/pkg/machine/vmconfigs"
|
||||
"github.com/containers/podman/v4/utils"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -51,7 +52,7 @@ func findQEMUBinary() (string, error) {
|
||||
|
||||
// setQMPMonitorSocket sets the virtual machine's QMP Monitor socket
|
||||
func (v *MachineVM) setQMPMonitorSocket() error {
|
||||
monitor, err := NewQMPMonitor("unix", v.Name, defaultQMPTimeout)
|
||||
monitor, err := newQMPMonitor("unix", v.Name, defaultQMPTimeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -74,7 +75,7 @@ func (v *MachineVM) setNewMachineCMD(qemuBinary string, cmdOpts *setNewMachineCM
|
||||
|
||||
// NewMachine initializes an instance of a virtual machine based on the qemu
|
||||
// virtualization.
|
||||
func (p *QEMUVirtualization) NewMachine(opts machine.InitOptions) (machine.VM, error) {
|
||||
func (p *QEMUVirtualization) NewMachine(opts define.InitOptions) (machine.VM, error) {
|
||||
vm := new(MachineVM)
|
||||
if len(opts.Name) > 0 {
|
||||
vm.Name = opts.Name
|
||||
@ -159,7 +160,7 @@ func (p *QEMUVirtualization) LoadVMByName(name string) (machine.VM, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lock, err := machine.GetLock(vm.Name, vmtype)
|
||||
lock, err := machine.GetLock(vm.Name, vmtype) //nolint:staticcheck
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"github.com/containers/common/pkg/config"
|
||||
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/connection"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/pkg/machine/ignition"
|
||||
"github.com/containers/podman/v4/pkg/machine/qemu/command"
|
||||
@ -84,7 +85,7 @@ type MachineVM struct {
|
||||
|
||||
// addMountsToVM converts the volumes passed through the CLI into the specified
|
||||
// volume driver and adds them to the machine
|
||||
func (v *MachineVM) addMountsToVM(opts machine.InitOptions) error {
|
||||
func (v *MachineVM) addMountsToVM(opts define.InitOptions) error {
|
||||
var volumeType string
|
||||
switch opts.VolumeDriver {
|
||||
// "" is the default volume driver
|
||||
@ -112,7 +113,7 @@ func (v *MachineVM) addMountsToVM(opts machine.InitOptions) error {
|
||||
|
||||
// Init writes the json configuration file to the filesystem for
|
||||
// other verbs (start, stop)
|
||||
func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
||||
func (v *MachineVM) Init(opts define.InitOptions) (bool, error) {
|
||||
var (
|
||||
key string
|
||||
err error
|
||||
@ -150,7 +151,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
||||
// Add location of bootable image
|
||||
v.CmdLine.SetBootableImage(v.getImageFile())
|
||||
|
||||
if err = machine.AddSSHConnectionsToPodmanSocket(
|
||||
if err = connection.AddSSHConnectionsToPodmanSocket(
|
||||
v.UID,
|
||||
v.Port,
|
||||
v.IdentityPath,
|
||||
@ -234,7 +235,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
||||
}
|
||||
|
||||
func (v *MachineVM) removeSystemConnections() error {
|
||||
return machine.RemoveConnections(v.Name, fmt.Sprintf("%s-root", v.Name))
|
||||
return connection.RemoveConnections(v.Name, fmt.Sprintf("%s-root", v.Name))
|
||||
}
|
||||
|
||||
func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) {
|
||||
@ -877,8 +878,8 @@ func (v *MachineVM) stopLocked() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewQMPMonitor creates the monitor subsection of our vm
|
||||
func NewQMPMonitor(network, name string, timeout time.Duration) (command.Monitor, error) {
|
||||
// Deprecated: newQMPMonitor creates the monitor subsection of our vm
|
||||
func newQMPMonitor(network, name string, timeout time.Duration) (command.Monitor, error) {
|
||||
rtDir, err := getRuntimeDir()
|
||||
if err != nil {
|
||||
return command.Monitor{}, err
|
||||
@ -991,7 +992,7 @@ func (v *MachineVM) Remove(_ string, opts machine.RemoveOptions) (string, func()
|
||||
|
||||
confirmationMessage += "\n"
|
||||
return confirmationMessage, func() error {
|
||||
machine.RemoveFilesAndConnections(files, v.Name, v.Name+"-root")
|
||||
connection.RemoveFilesAndConnections(files, v.Name, v.Name+"-root")
|
||||
return nil
|
||||
}, nil
|
||||
}
|
||||
|
69
pkg/machine/qemu/p5qemu/stubber.go
Normal file
69
pkg/machine/qemu/p5qemu/stubber.go
Normal file
@ -0,0 +1,69 @@
|
||||
package p5qemu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/pkg/machine/qemu/command"
|
||||
"github.com/containers/podman/v4/pkg/machine/vmconfigs"
|
||||
"github.com/go-openapi/errors"
|
||||
)
|
||||
|
||||
type QEMUStubber struct {
|
||||
vmconfigs.QEMUConfig
|
||||
}
|
||||
|
||||
func (q *QEMUStubber) CreateVM(opts define.CreateVMOpts, mc *vmconfigs.MachineConfig) error {
|
||||
fmt.Println("//// CreateVM: ", opts.Name)
|
||||
monitor, err := command.NewQMPMonitor(opts.Name, opts.Dirs.RuntimeDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
qemuConfig := vmconfigs.QEMUConfig{
|
||||
Command: nil,
|
||||
QMPMonitor: monitor,
|
||||
}
|
||||
|
||||
mc.QEMUHypervisor = &qemuConfig
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *QEMUStubber) StartVM() error {
|
||||
return errors.NotImplemented("")
|
||||
}
|
||||
|
||||
func (q *QEMUStubber) StopVM() error {
|
||||
return errors.NotImplemented("")
|
||||
}
|
||||
|
||||
func (q *QEMUStubber) InspectVM() error {
|
||||
return errors.NotImplemented("")
|
||||
}
|
||||
|
||||
func (q *QEMUStubber) RemoveVM() error {
|
||||
return errors.NotImplemented("")
|
||||
}
|
||||
|
||||
func (q *QEMUStubber) ChangeSettings() error {
|
||||
return errors.NotImplemented("")
|
||||
}
|
||||
|
||||
func (q *QEMUStubber) IsFirstBoot() error {
|
||||
return errors.NotImplemented("")
|
||||
}
|
||||
|
||||
func (q *QEMUStubber) SetupMounts() error {
|
||||
return errors.NotImplemented("")
|
||||
}
|
||||
|
||||
func (q *QEMUStubber) CheckExclusiveActiveVM() (bool, string, error) {
|
||||
return false, "", errors.NotImplemented("")
|
||||
}
|
||||
|
||||
func (q *QEMUStubber) GetHyperVisorVMs() ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (q *QEMUStubber) VMType() define.VMType {
|
||||
return define.QemuVirt
|
||||
}
|
1
pkg/machine/qemuprovider.go
Normal file
1
pkg/machine/qemuprovider.go
Normal file
@ -0,0 +1 @@
|
||||
package machine
|
@ -11,8 +11,6 @@ import (
|
||||
"github.com/containers/storage/pkg/lockfile"
|
||||
)
|
||||
|
||||
type aThing struct{}
|
||||
|
||||
type MachineConfig struct {
|
||||
// Common stuff
|
||||
Created time.Time
|
||||
@ -32,6 +30,8 @@ type MachineConfig struct {
|
||||
// Image stuff
|
||||
imageDescription machineImage //nolint:unused
|
||||
|
||||
ImagePath *define.VMFile // Temporary only until a proper image struct is worked out
|
||||
|
||||
// Provider stuff
|
||||
AppleHypervisor *AppleHVConfig `json:",omitempty"`
|
||||
QEMUHypervisor *QEMUConfig `json:",omitempty"`
|
||||
@ -39,11 +39,14 @@ type MachineConfig struct {
|
||||
WSLHypervisor *WSLConfig `json:",omitempty"`
|
||||
|
||||
lock *lockfile.LockFile //nolint:unused
|
||||
|
||||
// configPath can be used for reading, writing, removing
|
||||
configPath *define.VMFile
|
||||
}
|
||||
|
||||
// MachineImage describes a podman machine image
|
||||
type MachineImage struct {
|
||||
OCI *ociMachineImage
|
||||
OCI *OCIMachineImage
|
||||
FCOS *fcosMachineImage
|
||||
}
|
||||
|
||||
@ -63,7 +66,7 @@ type machineImage interface { //nolint:unused
|
||||
path() string
|
||||
}
|
||||
|
||||
type ociMachineImage struct {
|
||||
type OCIMachineImage struct {
|
||||
// registry
|
||||
// TODO JSON serial/deserial will write string to disk
|
||||
// but in code it is a types.ImageReference
|
||||
@ -72,11 +75,11 @@ type ociMachineImage struct {
|
||||
FQImageReference string
|
||||
}
|
||||
|
||||
func (o ociMachineImage) path() string {
|
||||
func (o OCIMachineImage) path() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (o ociMachineImage) download() error {
|
||||
func (o OCIMachineImage) download() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -94,6 +97,13 @@ func (f fcosMachineImage) path() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type VMStubber interface {
|
||||
CreateVM(opts define.CreateVMOpts, mc *MachineConfig) error
|
||||
VMType() define.VMType
|
||||
GetHyperVisorVMs() ([]string, error)
|
||||
}
|
||||
type aThing struct{}
|
||||
|
||||
// HostUser describes the host user
|
||||
type HostUser struct {
|
||||
// Whether this machine should run in a rootful or rootless manner
|
||||
|
@ -1,6 +1,8 @@
|
||||
package vmconfigs
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine/applehv/vfkit"
|
||||
)
|
||||
|
||||
@ -13,3 +15,7 @@ type AppleHVConfig struct {
|
||||
type HyperVConfig struct{}
|
||||
type WSLConfig struct{}
|
||||
type QEMUConfig struct{}
|
||||
|
||||
func getHostUID() int {
|
||||
return os.Getuid()
|
||||
}
|
||||
|
@ -1,7 +1,13 @@
|
||||
package vmconfigs
|
||||
|
||||
import "os"
|
||||
|
||||
// Stubs
|
||||
type HyperVConfig struct{}
|
||||
type WSLConfig struct {}
|
||||
type QEMUConfig struct {}
|
||||
type AppleHVConfig struct {}
|
||||
type WSLConfig struct{}
|
||||
type QEMUConfig struct{}
|
||||
type AppleHVConfig struct{}
|
||||
|
||||
func getHostUID() int {
|
||||
return os.Getuid()
|
||||
}
|
||||
|
@ -1,14 +1,22 @@
|
||||
package vmconfigs
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine/qemu/command"
|
||||
)
|
||||
|
||||
type QEMUConfig struct {
|
||||
cmd command.QemuCmd //nolint:unused
|
||||
Command command.QemuCmd
|
||||
// QMPMonitor is the qemu monitor object for sending commands
|
||||
QMPMonitor command.Monitor
|
||||
}
|
||||
|
||||
// Stubs
|
||||
type AppleHVConfig struct{}
|
||||
type HyperVConfig struct{}
|
||||
type WSLConfig struct{}
|
||||
|
||||
func getHostUID() int {
|
||||
return os.Getuid()
|
||||
}
|
||||
|
@ -19,3 +19,7 @@ type WSLConfig struct {
|
||||
// Stubs
|
||||
type QEMUConfig struct{}
|
||||
type AppleHVConfig struct{}
|
||||
|
||||
func getHostUID() int {
|
||||
return 1000
|
||||
}
|
||||
|
200
pkg/machine/vmconfigs/machine.go
Normal file
200
pkg/machine/vmconfigs/machine.go
Normal file
@ -0,0 +1,200 @@
|
||||
package vmconfigs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
define2 "github.com/containers/podman/v4/libpod/define"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
"github.com/containers/podman/v4/pkg/machine/lock"
|
||||
"github.com/containers/podman/v4/utils"
|
||||
)
|
||||
|
||||
/*
|
||||
info Display machine host info common
|
||||
init Initialize a virtual machine specific
|
||||
inspect Inspect an existing machine specific
|
||||
list List machines specific
|
||||
os Manage a Podman virtual machine's OS common
|
||||
rm Remove an existing machine specific
|
||||
set Set a virtual machine setting specific
|
||||
ssh SSH into an existing machine common
|
||||
start Start an existing machine specific
|
||||
stop Stop an existing machine specific
|
||||
*/
|
||||
|
||||
var (
|
||||
SSHRemoteConnection RemoteConnectionType = "ssh"
|
||||
DefaultIgnitionUserName = "core"
|
||||
ForwarderBinaryName = "gvproxy"
|
||||
)
|
||||
|
||||
type RemoteConnectionType string
|
||||
|
||||
// NewMachineConfig creates the initial machine configuration file from cli options
|
||||
func NewMachineConfig(opts define.InitOptions, machineConfigDir string) (*MachineConfig, error) {
|
||||
mc := new(MachineConfig)
|
||||
mc.Name = opts.Name
|
||||
|
||||
machineLock, err := lock.GetMachineLock(opts.Name, machineConfigDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mc.lock = machineLock
|
||||
|
||||
cf, err := define.NewMachineFile(filepath.Join(machineConfigDir, fmt.Sprintf("%s.json", opts.Name)), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mc.configPath = cf
|
||||
|
||||
// System Resources
|
||||
mrc := ResourceConfig{
|
||||
CPUs: opts.CPUS,
|
||||
DiskSize: opts.DiskSize,
|
||||
Memory: opts.Memory,
|
||||
USBs: nil, // Needs to be filled in by providers?
|
||||
}
|
||||
mc.Resources = mrc
|
||||
|
||||
sshPort, err := utils.GetRandomPort()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Single key examination should occur here
|
||||
sshConfig := SSHConfig{
|
||||
IdentityPath: "/home/baude/.local/share/containers/podman/machine", // TODO Fix this
|
||||
Port: sshPort,
|
||||
RemoteUsername: opts.Username,
|
||||
}
|
||||
|
||||
mc.SSH = sshConfig
|
||||
mc.Created = time.Now()
|
||||
|
||||
mc.HostUser = HostUser{UID: getHostUID(), Rootful: opts.Rootful}
|
||||
|
||||
// TODO - Temporarily disabled to make things easier
|
||||
/*
|
||||
// TODO AddSSHConnectionToPodmanSocket could put converted become a method of MachineConfig
|
||||
if err := connection.AddSSHConnectionsToPodmanSocket(mc.HostUser.UID, mc.SSH.Port, mc.SSH.IdentityPath, mc.Name, mc.SSH.RemoteUsername, opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
*/
|
||||
// addcallback for ssh connections here
|
||||
|
||||
return mc, nil
|
||||
}
|
||||
|
||||
// Lock creates a lock on the machine for single access
|
||||
func (mc *MachineConfig) Lock() {
|
||||
mc.lock.Lock()
|
||||
}
|
||||
|
||||
// Unlock removes an existing lock
|
||||
func (mc *MachineConfig) Unlock() {
|
||||
mc.lock.Unlock()
|
||||
}
|
||||
|
||||
// Write is a locking way to the machine configuration file
|
||||
func (mc *MachineConfig) Write() error {
|
||||
mc.Lock()
|
||||
defer mc.Unlock()
|
||||
return mc.write()
|
||||
}
|
||||
|
||||
// write is a non-locking way to write the machine configuration file to disk
|
||||
func (mc *MachineConfig) write() error {
|
||||
if mc.configPath == nil {
|
||||
return fmt.Errorf("no configuration file associated with vm %q", mc.Name)
|
||||
}
|
||||
b, err := json.Marshal(mc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Debugf("writing configuration file %q", mc.configPath.Path)
|
||||
return os.WriteFile(mc.configPath.GetPath(), b, define.DefaultFilePerm)
|
||||
}
|
||||
|
||||
func (mc *MachineConfig) removeSystemConnection() error { //nolint:unused
|
||||
return define2.ErrNotImplemented
|
||||
}
|
||||
|
||||
// updateLastBoot writes the current time to the machine configuration file. it is
|
||||
// an non-locking method and assumes it is being called locked
|
||||
func (mc *MachineConfig) updateLastBoot() error { //nolint:unused
|
||||
mc.LastUp = time.Now()
|
||||
return mc.Write()
|
||||
}
|
||||
|
||||
func (mc *MachineConfig) removeMachineFiles() error { //nolint:unused
|
||||
return define2.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (mc *MachineConfig) Info() error { // signature TBD
|
||||
return define2.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (mc *MachineConfig) OSApply() error { // signature TBD
|
||||
return define2.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (mc *MachineConfig) SecureShell() error { // Used SecureShell instead of SSH to do struct collision
|
||||
return define2.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (mc *MachineConfig) Inspect() error { // signature TBD
|
||||
return define2.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (mc *MachineConfig) ConfigDir() (string, error) {
|
||||
if mc.configPath == nil {
|
||||
return "", errors.New("no configuration directory set")
|
||||
}
|
||||
return filepath.Dir(mc.configPath.GetPath()), nil
|
||||
}
|
||||
|
||||
// LoadMachineByName returns a machine config based on the vm name and provider
|
||||
func LoadMachineByName(name, configDir string) (*MachineConfig, error) {
|
||||
fullPath := filepath.Join(configDir, fmt.Sprintf("%s.json", name))
|
||||
return loadMachineFromFQPath(fullPath)
|
||||
}
|
||||
|
||||
// loadMachineFromFQPath stub function for loading a JSON configuration file and returning
|
||||
// a machineconfig. this should only be called if you know what you are doing.
|
||||
func loadMachineFromFQPath(path string) (*MachineConfig, error) {
|
||||
mc := new(MachineConfig)
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(b, mc)
|
||||
return mc, err
|
||||
}
|
||||
|
||||
// LoadMachinesInDir returns all the machineconfigs located in given dir
|
||||
func LoadMachinesInDir(configDir string) (map[string]*MachineConfig, error) {
|
||||
mcs := make(map[string]*MachineConfig)
|
||||
if err := filepath.WalkDir(configDir, func(path string, d fs.DirEntry, err error) error {
|
||||
if strings.HasSuffix(d.Name(), ".json") {
|
||||
fullPath := filepath.Join(configDir, d.Name())
|
||||
mc, err := loadMachineFromFQPath(fullPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mcs[mc.Name] = mc
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mcs, nil
|
||||
}
|
@ -27,7 +27,7 @@ func VirtualizationProvider() machine.VirtProvider {
|
||||
}
|
||||
|
||||
// NewMachine initializes an instance of a wsl machine
|
||||
func (p *WSLVirtualization) NewMachine(opts machine.InitOptions) (machine.VM, error) {
|
||||
func (p *WSLVirtualization) NewMachine(opts define.InitOptions) (machine.VM, error) {
|
||||
vm := new(MachineVM)
|
||||
if len(opts.USBs) > 0 {
|
||||
return nil, fmt.Errorf("USB host passthrough is not supported for WSL machines")
|
||||
|
@ -16,6 +16,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/machine/connection"
|
||||
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/podman/v4/pkg/machine"
|
||||
"github.com/containers/podman/v4/pkg/machine/define"
|
||||
@ -394,7 +396,7 @@ func getLegacyLastStart(vm *MachineVM) time.Time {
|
||||
|
||||
// Init writes the json configuration file to the filesystem for
|
||||
// other verbs (start, stop)
|
||||
func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
||||
func (v *MachineVM) Init(opts define.InitOptions) (bool, error) {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
@ -495,10 +497,10 @@ func (v *MachineVM) removeMachineImage() error {
|
||||
}
|
||||
|
||||
func (v *MachineVM) removeSystemConnections() error {
|
||||
return machine.RemoveConnections(v.Name, fmt.Sprintf("%s-root", v.Name))
|
||||
return connection.RemoveConnections(v.Name, fmt.Sprintf("%s-root", v.Name))
|
||||
}
|
||||
|
||||
func downloadDistro(v *MachineVM, opts machine.InitOptions) error {
|
||||
func downloadDistro(v *MachineVM, opts define.InitOptions) error {
|
||||
var (
|
||||
dd machine.DistributionDownload
|
||||
err error
|
||||
@ -525,8 +527,8 @@ func (v *MachineVM) writeConfig() error {
|
||||
}
|
||||
|
||||
func constructSSHUris(v *MachineVM) ([]url.URL, []string) {
|
||||
uri := machine.SSHRemoteConnection.MakeSSHURL(machine.LocalhostIP, rootlessSock, strconv.Itoa(v.Port), v.RemoteUsername)
|
||||
uriRoot := machine.SSHRemoteConnection.MakeSSHURL(machine.LocalhostIP, rootfulSock, strconv.Itoa(v.Port), "root")
|
||||
uri := connection.SSHRemoteConnection.MakeSSHURL(connection.LocalhostIP, rootlessSock, strconv.Itoa(v.Port), v.RemoteUsername)
|
||||
uriRoot := connection.SSHRemoteConnection.MakeSSHURL(connection.LocalhostIP, rootfulSock, strconv.Itoa(v.Port), "root")
|
||||
|
||||
uris := []url.URL{uri, uriRoot}
|
||||
names := []string{v.Name, v.Name + "-root"}
|
||||
@ -534,7 +536,7 @@ func constructSSHUris(v *MachineVM) ([]url.URL, []string) {
|
||||
return uris, names
|
||||
}
|
||||
|
||||
func setupConnections(v *MachineVM, opts machine.InitOptions) error {
|
||||
func setupConnections(v *MachineVM, opts define.InitOptions) error {
|
||||
uris, names := constructSSHUris(v)
|
||||
|
||||
// The first connection defined when connections is empty will become the default
|
||||
@ -552,7 +554,7 @@ func setupConnections(v *MachineVM, opts machine.InitOptions) error {
|
||||
defer flock.unlock()
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
if err := machine.AddConnection(&uris[i], names[i], v.IdentityPath, opts.IsDefault && i == 0); err != nil {
|
||||
if err := connection.AddConnection(&uris[i], names[i], v.IdentityPath, opts.IsDefault && i == 0); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -809,7 +811,7 @@ func writeWslConf(dist string, user string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkAndInstallWSL(opts machine.InitOptions) (bool, error) {
|
||||
func checkAndInstallWSL(opts define.InitOptions) (bool, error) {
|
||||
if wutil.IsWSLInstalled() {
|
||||
return true, nil
|
||||
}
|
||||
@ -844,7 +846,7 @@ func checkAndInstallWSL(opts machine.InitOptions) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func attemptFeatureInstall(opts machine.InitOptions, admin bool) error {
|
||||
func attemptFeatureInstall(opts define.InitOptions, admin bool) error {
|
||||
if !winVersionAtLeast(10, 0, 18362) {
|
||||
return errors.New("your version of Windows does not support WSL. Update to Windows 10 Build 19041 or later")
|
||||
} else if !winVersionAtLeast(10, 0, 19041) {
|
||||
@ -1276,7 +1278,7 @@ func (v *MachineVM) reassignSshPort() error {
|
||||
v.Port = newPort
|
||||
uris, names := constructSSHUris(v)
|
||||
for i := 0; i < 2; i++ {
|
||||
if err := machine.ChangeConnectionURI(names[i], &uris[i]); err != nil {
|
||||
if err := connection.ChangeConnectionURI(names[i], &uris[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -1476,7 +1478,7 @@ func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, fun
|
||||
|
||||
confirmationMessage += "\n"
|
||||
return confirmationMessage, func() error {
|
||||
if err := machine.RemoveConnections(v.Name, v.Name+"-root"); err != nil {
|
||||
if err := connection.RemoveConnections(v.Name, v.Name+"-root"); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
if err := runCmdPassThrough("wsl", "--unregister", toDist(v.Name)); err != nil {
|
||||
|
Reference in New Issue
Block a user