Merge pull request #20692 from jakecorrenti/ignition-pkg

Create `pkg/machine/ignition` package
This commit is contained in:
openshift-merge-bot[bot]
2024-01-04 18:10:46 +00:00
committed by GitHub
33 changed files with 427 additions and 322 deletions

View File

@ -187,7 +187,7 @@ func composeDockerHost() (string, error) {
if info.State != define.Running { if info.State != define.Running {
return "", fmt.Errorf("machine %s is not running but in state %s", item.Name, info.State) return "", fmt.Errorf("machine %s is not running but in state %s", item.Name, info.State)
} }
if machineProvider.VMType() == machine.WSLVirt { if machineProvider.VMType() == define.WSLVirt {
if info.ConnectionInfo.PodmanPipe == nil { if info.ConnectionInfo.PodmanPipe == nil {
return "", errors.New("pipe of machine is not set") return "", errors.New("pipe of machine is not set")
} }

View File

@ -11,6 +11,7 @@ import (
"github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/libpod/events" "github.com/containers/podman/v4/libpod/events"
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -141,7 +142,7 @@ func initMachine(cmd *cobra.Command, args []string) error {
} }
// The vmtype names need to be reserved and cannot be used for podman machine names // The vmtype names need to be reserved and cannot be used for podman machine names
if _, err := machine.ParseVMType(initOpts.Name, machine.UnknownVirt); err == nil { if _, err := define.ParseVMType(initOpts.Name, define.UnknownVirt); err == nil {
return fmt.Errorf("cannot use %q for a machine name", initOpts.Name) return fmt.Errorf("cannot use %q for a machine name", initOpts.Name)
} }

View File

@ -13,6 +13,7 @@ import (
"github.com/containers/podman/v4/pkg/machine/compression" "github.com/containers/podman/v4/pkg/machine/compression"
"github.com/containers/podman/v4/pkg/machine/define" "github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/machine/vmconfigs" "github.com/containers/podman/v4/pkg/machine/vmconfigs"
"github.com/containers/podman/v4/pkg/machine/ignition"
vfConfig "github.com/crc-org/vfkit/pkg/config" vfConfig "github.com/crc-org/vfkit/pkg/config"
"github.com/docker/go-units" "github.com/docker/go-units"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
@ -55,7 +56,7 @@ func (v AppleHVVirtualization) CheckExclusiveActiveVM() (bool, string, error) {
} }
func (v AppleHVVirtualization) IsValidVMName(name string) (bool, error) { func (v AppleHVVirtualization) IsValidVMName(name string) (bool, error) {
configDir, err := machine.GetConfDir(machine.AppleHvVirt) configDir, err := machine.GetConfDir(define.AppleHvVirt)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -93,7 +94,7 @@ func (v AppleHVVirtualization) List(opts machine.ListOptions) ([]*machine.ListRe
Running: vmState == define.Running, Running: vmState == define.Running,
Starting: vmState == define.Starting, Starting: vmState == define.Starting,
Stream: mm.ImageStream, Stream: mm.ImageStream,
VMType: machine.AppleHvVirt.String(), VMType: define.AppleHvVirt.String(),
CPUs: mm.CPUs, CPUs: mm.CPUs,
Memory: mm.Memory * units.MiB, Memory: mm.Memory * units.MiB,
DiskSize: mm.DiskSize * units.GiB, DiskSize: mm.DiskSize * units.GiB,
@ -118,7 +119,7 @@ func (v AppleHVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM,
return nil, fmt.Errorf("USB host passthrough is not supported for applehv machines") return nil, fmt.Errorf("USB host passthrough is not supported for applehv machines")
} }
configDir, err := machine.GetConfDir(machine.AppleHvVirt) configDir, err := machine.GetConfDir(define.AppleHvVirt)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -129,12 +130,12 @@ func (v AppleHVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM,
} }
m.ConfigPath = *configPath m.ConfigPath = *configPath
dataDir, err := machine.GetDataDir(machine.AppleHvVirt) dataDir, err := machine.GetDataDir(define.AppleHvVirt)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := machine.SetIgnitionFile(&m.IgnitionFile, vmtype, m.Name); err != nil { if err := ignition.SetIgnitionFile(&m.IgnitionFile, vmtype, m.Name, configDir); err != nil {
return nil, err return nil, err
} }
@ -161,7 +162,7 @@ func (v AppleHVVirtualization) RemoveAndCleanMachines() error {
return machine.ErrNotImplemented return machine.ErrNotImplemented
} }
func (v AppleHVVirtualization) VMType() machine.VMType { func (v AppleHVVirtualization) VMType() define.VMType {
return vmtype return vmtype
} }

View File

@ -24,7 +24,9 @@ import (
"github.com/containers/podman/v4/pkg/machine/define" "github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/machine/sockets" "github.com/containers/podman/v4/pkg/machine/sockets"
"github.com/containers/podman/v4/pkg/machine/vmconfigs" "github.com/containers/podman/v4/pkg/machine/vmconfigs"
"github.com/containers/podman/v4/pkg/machine/ignition"
"github.com/containers/podman/v4/pkg/strongunits" "github.com/containers/podman/v4/pkg/strongunits"
"github.com/containers/podman/v4/pkg/systemd/parser"
"github.com/containers/podman/v4/pkg/util" "github.com/containers/podman/v4/pkg/util"
"github.com/containers/podman/v4/utils" "github.com/containers/podman/v4/utils"
"github.com/containers/storage/pkg/lockfile" "github.com/containers/storage/pkg/lockfile"
@ -36,7 +38,7 @@ import (
var ( var (
// vmtype refers to qemu (vs libvirt, krun, etc). // vmtype refers to qemu (vs libvirt, krun, etc).
vmtype = machine.AppleHvVirt vmtype = define.AppleHvVirt
) )
const ( const (
@ -45,21 +47,13 @@ const (
apiUpTimeout = 20 * time.Second apiUpTimeout = 20 * time.Second
) )
// appleHVReadyUnit is a unit file that sets up the virtual serial device // VfkitHelper describes the use of vfkit: cmdline and endpoint
// where when the VM is done configuring, it will send an ack type VfkitHelper struct {
// so a listening host knows it can begin interacting with it LogLevel logrus.Level
const appleHVReadyUnit = `[Unit] Endpoint string
Requires=dev-virtio\\x2dports-%s.device VfkitBinaryPath *define.VMFile
After=remove-moby.service sshd.socket sshd.service VirtualMachine *vfConfig.VirtualMachine
OnFailure=emergency.target }
OnFailureJobMode=isolate
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/sh -c '/usr/bin/echo Ready | socat - VSOCK-CONNECT:2:1025'
[Install]
RequiredBy=default.target
`
type MacMachine struct { type MacMachine struct {
// ConfigPath is the fully qualified path to the configuration file // ConfigPath is the fully qualified path to the configuration file
@ -160,7 +154,7 @@ func (m *MacMachine) Init(opts machine.InitOptions) (bool, error) {
go callbackFuncs.CleanOnSignal() go callbackFuncs.CleanOnSignal()
callbackFuncs.Add(m.ConfigPath.Delete) callbackFuncs.Add(m.ConfigPath.Delete)
dataDir, err := machine.GetDataDir(machine.AppleHvVirt) dataDir, err := machine.GetDataDir(define.AppleHvVirt)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -254,11 +248,11 @@ func (m *MacMachine) Init(opts machine.InitOptions) (bool, error) {
callbackFuncs.Add(m.removeSSHKeys) callbackFuncs.Add(m.removeSSHKeys)
} }
builder := machine.NewIgnitionBuilder(machine.DynamicIgnition{ builder := ignition.NewIgnitionBuilder(ignition.DynamicIgnition{
Name: opts.Username, Name: opts.Username,
Key: key, Key: key,
VMName: m.Name, VMName: m.Name,
VMType: machine.AppleHvVirt, VMType: define.AppleHvVirt,
TimeZone: opts.TimeZone, TimeZone: opts.TimeZone,
WritePath: m.IgnitionFile.GetPath(), WritePath: m.IgnitionFile.GetPath(),
UID: m.UID, UID: m.UID,
@ -273,10 +267,15 @@ func (m *MacMachine) Init(opts machine.InitOptions) (bool, error) {
return false, err return false, err
} }
builder.WithUnit(machine.Unit{ readyUnitFile, err := createReadyUnitFile()
Enabled: machine.BoolToPtr(true), if err != nil {
return false, err
}
builder.WithUnit(ignition.Unit{
Enabled: ignition.BoolToPtr(true),
Name: "ready.service", Name: "ready.service",
Contents: machine.StrToPtr(fmt.Sprintf(appleHVReadyUnit, "vsock")), Contents: ignition.StrToPtr(readyUnitFile),
}) })
builder.WithUnit(generateSystemDFilesForVirtiofsMounts(virtiofsMnts)...) builder.WithUnit(generateSystemDFilesForVirtiofsMounts(virtiofsMnts)...)
@ -287,6 +286,13 @@ func (m *MacMachine) Init(opts machine.InitOptions) (bool, error) {
return err == nil, err return err == nil, err
} }
func createReadyUnitFile() (string, error) {
readyUnit := ignition.DefaultReadyUnitFile()
readyUnit.Add("Unit", "Requires", "dev-virtio\\x2dports-vsock.device")
readyUnit.Add("Service", "ExecStart", "/bin/sh -c '/usr/bin/echo Ready | socat - VSOCK-CONNECT:2:1025'")
return readyUnit.ToString()
}
func (m *MacMachine) removeSSHKeys() error { func (m *MacMachine) removeSSHKeys() error {
if err := os.Remove(fmt.Sprintf("%s.pub", m.IdentityPath)); err != nil { if err := os.Remove(fmt.Sprintf("%s.pub", m.IdentityPath)); err != nil {
logrus.Error(err) logrus.Error(err)
@ -786,7 +792,7 @@ func loadMacMachineFromJSON(fqConfigPath string) (*MacMachine, error) {
} }
func (m *MacMachine) jsonConfigPath() (string, error) { func (m *MacMachine) jsonConfigPath() (string, error) {
configDir, err := machine.GetConfDir(machine.AppleHvVirt) configDir, err := machine.GetConfDir(define.AppleHvVirt)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -817,7 +823,7 @@ func getVMInfos() ([]*machine.ListResponse, error) {
listEntry.Name = vm.Name listEntry.Name = vm.Name
listEntry.Stream = vm.ImageStream listEntry.Stream = vm.ImageStream
listEntry.VMType = machine.AppleHvVirt.String() listEntry.VMType = define.AppleHvVirt.String()
listEntry.CPUs = vm.CPUs listEntry.CPUs = vm.CPUs
listEntry.Memory = vm.Memory * units.MiB listEntry.Memory = vm.Memory * units.MiB
listEntry.DiskSize = vm.DiskSize * units.GiB listEntry.DiskSize = vm.DiskSize * units.GiB
@ -1014,7 +1020,7 @@ func (m *MacMachine) setupAPIForwarding(cmd gvproxy.GvproxyCommand) (gvproxy.Gvp
} }
func (m *MacMachine) dockerSock() (string, error) { func (m *MacMachine) dockerSock() (string, error) {
dd, err := machine.GetDataDir(machine.AppleHvVirt) dd, err := machine.GetDataDir(define.AppleHvVirt)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -1023,7 +1029,7 @@ func (m *MacMachine) dockerSock() (string, error) {
func (m *MacMachine) forwardSocketPath() (*define.VMFile, error) { func (m *MacMachine) forwardSocketPath() (*define.VMFile, error) {
sockName := "podman.sock" sockName := "podman.sock"
path, err := machine.GetDataDir(machine.AppleHvVirt) path, err := machine.GetDataDir(define.AppleHvVirt)
if err != nil { if err != nil {
return nil, fmt.Errorf("Resolving data dir: %s", err.Error()) return nil, fmt.Errorf("Resolving data dir: %s", err.Error())
} }
@ -1060,7 +1066,7 @@ func (m *MacMachine) isFirstBoot() (bool, error) {
} }
func (m *MacMachine) getIgnitionSock() (*define.VMFile, error) { func (m *MacMachine) getIgnitionSock() (*define.VMFile, error) {
dataDir, err := machine.GetDataDir(machine.AppleHvVirt) dataDir, err := machine.GetDataDir(define.AppleHvVirt)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1087,7 +1093,7 @@ func (m *MacMachine) getRuntimeDir() (string, error) {
} }
func (m *MacMachine) userGlobalSocketLink() (string, error) { func (m *MacMachine) userGlobalSocketLink() (string, error) {
path, err := machine.GetDataDir(machine.AppleHvVirt) path, err := machine.GetDataDir(define.AppleHvVirt)
if err != nil { if err != nil {
logrus.Errorf("Resolving data dir: %s", err.Error()) logrus.Errorf("Resolving data dir: %s", err.Error())
return "", err return "", err
@ -1100,46 +1106,49 @@ func (m *MacMachine) isIncompatible() bool {
return m.UID == -1 return m.UID == -1
} }
func generateSystemDFilesForVirtiofsMounts(mounts []machine.VirtIoFs) []machine.Unit { func generateSystemDFilesForVirtiofsMounts(mounts []machine.VirtIoFs) []ignition.Unit {
// mounting in fcos with virtiofs is a bit of a dance. we need a unit file for the mount, a unit file // mounting in fcos with virtiofs is a bit of a dance. we need a unit file for the mount, a unit file
// for automatic mounting on boot, and a "preparatory" service file that disables FCOS security, performs // for automatic mounting on boot, and a "preparatory" service file that disables FCOS security, performs
// the mkdir of the mount point, and then re-enables security. This must be done for each mount. // the mkdir of the mount point, and then re-enables security. This must be done for each mount.
var unitFiles []machine.Unit var unitFiles []ignition.Unit
for _, mnt := range mounts { for _, mnt := range mounts {
// Here we are looping the mounts and for each mount, we are adding two unit files // Here we are looping the mounts and for each mount, we are adding two unit files
// for virtiofs. One unit file is the mount itself and the second is to automount it // for virtiofs. One unit file is the mount itself and the second is to automount it
// on boot. // on boot.
autoMountUnit := `[Automount] autoMountUnit := parser.NewUnitFile()
Where=%s autoMountUnit.Add("Automount", "Where", "%s")
[Install] autoMountUnit.Add("Install", "WantedBy", "multi-user.target")
WantedBy=multi-user.target autoMountUnit.Add("Unit", "Description", "Mount virtiofs volume %s")
autoMountUnitFile, err := autoMountUnit.ToString()
[Unit] if err != nil {
Description=Mount virtiofs volume %s logrus.Warnf(err.Error())
`
mountUnit := `[Mount]
What=%s
Where=%s
Type=virtiofs
[Install]
WantedBy=multi-user.target
`
virtiofsAutomount := machine.Unit{
Enabled: machine.BoolToPtr(true),
Name: fmt.Sprintf("%s.automount", mnt.Tag),
Contents: machine.StrToPtr(fmt.Sprintf(autoMountUnit, mnt.Target, mnt.Target)),
} }
virtiofsMount := machine.Unit{
Enabled: machine.BoolToPtr(true), mountUnit := parser.NewUnitFile()
mountUnit.Add("Mount", "What", "%s")
mountUnit.Add("Mount", "Where", "%s")
mountUnit.Add("Mount", "Type", "virtiofs")
mountUnit.Add("Install", "WantedBy", "multi-user.target")
mountUnitFile, err := mountUnit.ToString()
if err != nil {
logrus.Warnf(err.Error())
}
virtiofsAutomount := ignition.Unit{
Enabled: ignition.BoolToPtr(true),
Name: fmt.Sprintf("%s.automount", mnt.Tag),
Contents: ignition.StrToPtr(fmt.Sprintf(autoMountUnitFile, mnt.Target, mnt.Target)),
}
virtiofsMount := ignition.Unit{
Enabled: ignition.BoolToPtr(true),
Name: fmt.Sprintf("%s.mount", mnt.Tag), Name: fmt.Sprintf("%s.mount", mnt.Tag),
Contents: machine.StrToPtr(fmt.Sprintf(mountUnit, mnt.Tag, mnt.Target)), Contents: ignition.StrToPtr(fmt.Sprintf(mountUnitFile, mnt.Tag, mnt.Target)),
} }
// This "unit" simulates something like systemctl enable virtiofs-mount-prepare@ // This "unit" simulates something like systemctl enable virtiofs-mount-prepare@
enablePrep := machine.Unit{ enablePrep := ignition.Unit{
Enabled: machine.BoolToPtr(true), Enabled: ignition.BoolToPtr(true),
Name: fmt.Sprintf("virtiofs-mount-prepare@%s.service", mnt.Tag), Name: fmt.Sprintf("virtiofs-mount-prepare@%s.service", mnt.Tag),
} }
@ -1148,23 +1157,24 @@ WantedBy=multi-user.target
// mount prep is a way to workaround the FCOS limitation of creating directories // mount prep is a way to workaround the FCOS limitation of creating directories
// at the rootfs / and then mounting to them. // at the rootfs / and then mounting to them.
mountPrep := ` mountPrep := parser.NewUnitFile()
[Unit] mountPrep.Add("Unit", "Description", "Allow virtios to mount to /")
Description=Allow virtios to mount to / mountPrep.Add("Unit", "DefaultDependencies", "no")
DefaultDependencies=no mountPrep.Add("Unit", "ConditionPathExists", "!%f")
ConditionPathExists=!%f
[Service] mountPrep.Add("Service", "Type", "oneshot")
Type=oneshot mountPrep.Add("Service", "ExecStartPre", "chattr -i /")
ExecStartPre=chattr -i / mountPrep.Add("Service", "ExecStart", "mkdir -p '%f'")
ExecStart=mkdir -p '%f' mountPrep.Add("Service", "ExecStopPost", "chattr +i /")
ExecStopPost=chattr +i /
[Install] mountPrep.Add("Install", "WantedBy", "remote-fs.target")
WantedBy=remote-fs.target mountPrepFile, err := mountPrep.ToString()
` if err != nil {
virtioFSChattr := machine.Unit{ logrus.Warnf(err.Error())
Contents: machine.StrToPtr(mountPrep), }
virtioFSChattr := ignition.Unit{
Contents: ignition.StrToPtr(mountPrepFile),
Name: "virtiofs-mount-prepare@.service", Name: "virtiofs-mount-prepare@.service",
} }
unitFiles = append(unitFiles, virtioFSChattr) unitFiles = append(unitFiles, virtioFSChattr)

View File

@ -14,7 +14,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/containers/common/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/compression" "github.com/containers/podman/v4/pkg/machine/compression"
"github.com/containers/podman/v4/pkg/machine/define" "github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/machine/vmconfigs" "github.com/containers/podman/v4/pkg/machine/vmconfigs"
@ -51,9 +50,8 @@ const (
type RemoteConnectionType string type RemoteConnectionType string
var ( var (
SSHRemoteConnection RemoteConnectionType = "ssh" SSHRemoteConnection RemoteConnectionType = "ssh"
DefaultIgnitionUserName = "core" ForwarderBinaryName = "gvproxy"
ForwarderBinaryName = "gvproxy"
) )
type Download struct { type Download struct {
@ -69,7 +67,7 @@ type Download struct {
Sha256sum string Sha256sum string
Size int64 Size int64
URL *url.URL URL *url.URL
VMKind VMType VMKind define.VMType
VMName string VMName string
} }
@ -133,7 +131,7 @@ type VM interface {
Stop(name string, opts StopOptions) error Stop(name string, opts StopOptions) error
} }
func GetLock(name string, vmtype VMType) (*lockfile.LockFile, error) { func GetLock(name string, vmtype define.VMType) (*lockfile.LockFile, error) {
// FIXME: there's a painful amount of `GetConfDir` calls scattered // FIXME: there's a painful amount of `GetConfDir` calls scattered
// across the code base. This should be done once and stored // across the code base. This should be done once and stored
// somewhere instead. // somewhere instead.
@ -191,7 +189,7 @@ func (rc RemoteConnectionType) MakeSSHURL(host, path, port, userName string) url
} }
// GetCacheDir returns the dir where VM images are downloaded into when pulled // GetCacheDir returns the dir where VM images are downloaded into when pulled
func GetCacheDir(vmType VMType) (string, error) { func GetCacheDir(vmType define.VMType) (string, error) {
dataDir, err := GetDataDir(vmType) dataDir, err := GetDataDir(vmType)
if err != nil { if err != nil {
return "", err return "", err
@ -205,7 +203,7 @@ func GetCacheDir(vmType VMType) (string, error) {
// GetDataDir returns the filepath where vm images should // GetDataDir returns the filepath where vm images should
// live for podman-machine. // live for podman-machine.
func GetDataDir(vmType VMType) (string, error) { func GetDataDir(vmType define.VMType) (string, error) {
dataDirPrefix, err := DataDirPrefix() dataDirPrefix, err := DataDirPrefix()
if err != nil { if err != nil {
return "", err return "", err
@ -241,7 +239,7 @@ func DataDirPrefix() (string, error) {
// GetConfigDir returns the filepath to where configuration // GetConfigDir returns the filepath to where configuration
// files for podman-machine should live // files for podman-machine should live
func GetConfDir(vmType VMType) (string, error) { func GetConfDir(vmType define.VMType) (string, error) {
confDirPrefix, err := ConfDirPrefix() confDirPrefix, err := ConfDirPrefix()
if err != nil { if err != nil {
return "", err return "", err
@ -283,28 +281,6 @@ type ConnectionConfig struct {
PodmanPipe *define.VMFile `json:"PodmanPipe"` PodmanPipe *define.VMFile `json:"PodmanPipe"`
} }
type VMType int64
const (
QemuVirt VMType = iota
WSLVirt
AppleHvVirt
HyperVVirt
UnknownVirt
)
func (v VMType) String() string {
switch v {
case WSLVirt:
return machine.Wsl
case AppleHvVirt:
return machine.AppleHV
case HyperVVirt:
return machine.HyperV
}
return machine.Qemu
}
type APIForwardingState int type APIForwardingState int
const ( const (
@ -315,23 +291,6 @@ const (
DockerGlobal DockerGlobal
) )
func ParseVMType(input string, emptyFallback VMType) (VMType, error) {
switch strings.TrimSpace(strings.ToLower(input)) {
case "qemu":
return QemuVirt, nil
case "wsl":
return WSLVirt, nil
case "applehv":
return AppleHvVirt, nil
case "hyperv":
return HyperVVirt, nil
case "":
return emptyFallback, nil
default:
return UnknownVirt, fmt.Errorf("unknown VMType `%s`", input)
}
}
type VirtProvider interface { //nolint:interfacebloat type VirtProvider interface { //nolint:interfacebloat
Artifact() define.Artifact Artifact() define.Artifact
CheckExclusiveActiveVM() (bool, string, error) CheckExclusiveActiveVM() (bool, string, error)
@ -343,14 +302,14 @@ type VirtProvider interface { //nolint:interfacebloat
NewMachine(opts InitOptions) (VM, error) NewMachine(opts InitOptions) (VM, error)
NewDownload(vmName string) (Download, error) NewDownload(vmName string) (Download, error)
RemoveAndCleanMachines() error RemoveAndCleanMachines() error
VMType() VMType VMType() define.VMType
} }
type Virtualization struct { type Virtualization struct {
artifact define.Artifact artifact define.Artifact
compression compression.ImageCompression compression compression.ImageCompression
format define.ImageFormat format define.ImageFormat
vmKind VMType vmKind define.VMType
} }
func (p *Virtualization) Artifact() define.Artifact { func (p *Virtualization) Artifact() define.Artifact {
@ -365,7 +324,7 @@ func (p *Virtualization) Format() define.ImageFormat {
return p.format return p.format
} }
func (p *Virtualization) VMType() VMType { func (p *Virtualization) VMType() define.VMType {
return p.vmKind return p.vmKind
} }
@ -391,7 +350,7 @@ func (p *Virtualization) NewDownload(vmName string) (Download, error) {
}, nil }, nil
} }
func NewVirtualization(artifact define.Artifact, compression compression.ImageCompression, format define.ImageFormat, vmKind VMType) Virtualization { func NewVirtualization(artifact define.Artifact, compression compression.ImageCompression, format define.ImageFormat, vmKind define.VMType) Virtualization {
return Virtualization{ return Virtualization{
artifact, artifact,
compression, compression,

View File

@ -0,0 +1,54 @@
package define
import (
"fmt"
"strings"
)
type VMType int64
const (
QemuVirt VMType = iota
WSLVirt
AppleHvVirt
HyperVVirt
UnknownVirt
)
// these constants are not exported due to a conflict with the constants defined
// in define/machine_artifact.go
const (
wsl = "wsl"
qemu = "qemu"
appleHV = "applehv"
hyperV = "hyperv"
)
func (v VMType) String() string {
switch v {
case WSLVirt:
return wsl
case AppleHvVirt:
return appleHV
case HyperVVirt:
return hyperV
}
return qemu
}
func ParseVMType(input string, emptyFallback VMType) (VMType, error) {
switch strings.TrimSpace(strings.ToLower(input)) {
case qemu:
return QemuVirt, nil
case wsl:
return WSLVirt, nil
case appleHV:
return AppleHvVirt, nil
case hyperV:
return HyperVVirt, nil
case "":
return emptyFallback, nil
default:
return UnknownVirt, fmt.Errorf("unknown VMType `%s`", input)
}
}

View File

@ -0,0 +1,58 @@
//go:build (amd64 && !windows) || (arm64 && !windows)
// +build amd64,!windows arm64,!windows
package define
import "testing"
func TestParseVMType(t *testing.T) {
type fields struct {
input string
fallback VMType
}
tests := []struct {
name string
fields fields
want VMType
}{
{
name: "Qemu input",
fields: fields{"qemu", QemuVirt},
want: QemuVirt,
},
{
name: "Applehv input",
fields: fields{"applehv", QemuVirt},
want: AppleHvVirt,
},
{
name: "Hyperv input",
fields: fields{"hyperv", QemuVirt},
want: HyperVVirt,
},
{
name: "WSL input",
fields: fields{"wsl", QemuVirt},
want: WSLVirt,
},
{
name: "Qemu empty fallback",
fields: fields{"", QemuVirt},
want: QemuVirt,
},
{
name: "Invalid input",
fields: fields{"riscv", AppleHvVirt},
want: UnknownVirt,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got, _ := ParseVMType(tt.fields.input, tt.fields.fallback); got != tt.want {
t.Errorf("ParseVMType(%s, %v) = %v, want %v", tt.fields.input, tt.fields.fallback, got, tt.want)
}
})
}
}

View File

@ -11,6 +11,7 @@ import (
"time" "time"
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/util" "github.com/containers/podman/v4/pkg/util"
"github.com/containers/storage/pkg/stringid" "github.com/containers/storage/pkg/stringid"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
@ -210,29 +211,29 @@ func (matcher *ValidJSONMatcher) NegatedFailureMessage(actual interface{}) (mess
return format.Message(actual, "to _not_ be valid JSON") return format.Message(actual, "to _not_ be valid JSON")
} }
func skipIfVmtype(vmType machine.VMType, message string) { func skipIfVmtype(vmType define.VMType, message string) {
if isVmtype(vmType) { if isVmtype(vmType) {
Skip(message) Skip(message)
} }
} }
func skipIfNotVmtype(vmType machine.VMType, message string) { func skipIfNotVmtype(vmType define.VMType, message string) {
if !isVmtype(vmType) { if !isVmtype(vmType) {
Skip(message) Skip(message)
} }
} }
func skipIfWSL(message string) { func skipIfWSL(message string) {
skipIfVmtype(machine.WSLVirt, message) skipIfVmtype(define.WSLVirt, message)
} }
func isVmtype(vmType machine.VMType) bool { func isVmtype(vmType define.VMType) bool {
return testProvider.VMType() == vmType return testProvider.VMType() == vmType
} }
// isWSL is a simple wrapper to determine if the testprovider is WSL // isWSL is a simple wrapper to determine if the testprovider is WSL
func isWSL() bool { func isWSL() bool {
return isVmtype(machine.WSLVirt) return isVmtype(define.WSLVirt)
} }
func getFCOSDownloadLocation(p machine.VirtProvider) string { func getFCOSDownloadLocation(p machine.VirtProvider) string {

View File

@ -6,6 +6,7 @@ import (
"strings" "strings"
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/machine/wsl" "github.com/containers/podman/v4/pkg/machine/wsl"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
) )
@ -13,10 +14,10 @@ import (
const podmanBinary = "../../../bin/windows/podman.exe" const podmanBinary = "../../../bin/windows/podman.exe"
func getDownloadLocation(p machine.VirtProvider) string { func getDownloadLocation(p machine.VirtProvider) string {
if p.VMType() == machine.HyperVVirt { if p.VMType() == define.HyperVVirt {
return getFCOSDownloadLocation(p) return getFCOSDownloadLocation(p)
} }
fd, err := wsl.NewFedoraDownloader(machine.WSLVirt, "", defaultStream.String()) fd, err := wsl.NewFedoraDownloader(define.WSLVirt, "", defaultStream.String())
if err != nil { if err != nil {
Fail("unable to get WSL virtual image") Fail("unable to get WSL virtual image")
} }

View File

@ -8,7 +8,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define" "github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/utils" "github.com/containers/podman/v4/utils"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
@ -80,7 +79,7 @@ var _ = Describe("podman machine init", func() {
testMachine := inspectBefore[0] testMachine := inspectBefore[0]
Expect(testMachine.Name).To(Equal(mb.names[0])) Expect(testMachine.Name).To(Equal(mb.names[0]))
if testProvider.VMType() != machine.WSLVirt { // WSL hardware specs are hardcoded if testProvider.VMType() != define.WSLVirt { // WSL hardware specs are hardcoded
Expect(testMachine.Resources.CPUs).To(Equal(uint64(cpus))) Expect(testMachine.Resources.CPUs).To(Equal(uint64(cpus)))
Expect(testMachine.Resources.Memory).To(Equal(uint64(2048))) Expect(testMachine.Resources.Memory).To(Equal(uint64(2048)))
} }
@ -136,7 +135,7 @@ var _ = Describe("podman machine init", func() {
Expect(inspectBefore).ToNot(BeEmpty()) Expect(inspectBefore).ToNot(BeEmpty())
testMachine := inspectBefore[0] testMachine := inspectBefore[0]
Expect(testMachine.Name).To(Equal(mb.names[0])) Expect(testMachine.Name).To(Equal(mb.names[0]))
if testProvider.VMType() != machine.WSLVirt { // memory and cpus something we cannot set with WSL if testProvider.VMType() != define.WSLVirt { // memory and cpus something we cannot set with WSL
Expect(testMachine.Resources.CPUs).To(Equal(uint64(cpus))) Expect(testMachine.Resources.CPUs).To(Equal(uint64(cpus)))
Expect(testMachine.Resources.Memory).To(Equal(uint64(2048))) Expect(testMachine.Resources.Memory).To(Equal(uint64(2048)))
} }
@ -186,7 +185,7 @@ var _ = Describe("podman machine init", func() {
}) })
It("machine init with volume", func() { It("machine init with volume", func() {
if testProvider.VMType() == machine.HyperVVirt { if testProvider.VMType() == define.HyperVVirt {
Skip("volumes are not supported on hyperv yet") Skip("volumes are not supported on hyperv yet")
} }
skipIfWSL("WSL volumes are much different. This test will not pass as is") skipIfWSL("WSL volumes are much different. This test will not pass as is")
@ -262,7 +261,7 @@ var _ = Describe("podman machine init", func() {
}) })
It("init with user mode networking", func() { It("init with user mode networking", func() {
if testProvider.VMType() != machine.WSLVirt { if testProvider.VMType() != define.WSLVirt {
Skip("test is only supported by WSL") Skip("test is only supported by WSL")
} }
i := new(initMachine) i := new(initMachine)
@ -327,7 +326,7 @@ var _ = Describe("podman machine init", func() {
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
// WSL does not use ignition // WSL does not use ignition
if testProvider.VMType() != machine.WSLVirt { if testProvider.VMType() != define.WSLVirt {
_, err = os.Stat(ign) _, err = os.Stat(ign)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
} }

View File

@ -2,6 +2,7 @@ package e2e_test
import ( import (
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define"
jsoniter "github.com/json-iterator/go" jsoniter "github.com/json-iterator/go"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
@ -66,7 +67,7 @@ var _ = Describe("podman inspect stop", func() {
err = jsoniter.Unmarshal(inspectSession.Bytes(), &inspectInfo) err = jsoniter.Unmarshal(inspectSession.Bytes(), &inspectInfo)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
switch testProvider.VMType() { switch testProvider.VMType() {
case machine.WSLVirt: case define.WSLVirt:
Expect(inspectInfo[0].ConnectionInfo.PodmanPipe.GetPath()).To(ContainSubstring("podman-")) Expect(inspectInfo[0].ConnectionInfo.PodmanPipe.GetPath()).To(ContainSubstring("podman-"))
default: default:
Expect(inspectInfo[0].ConnectionInfo.PodmanSocket.GetPath()).To(HaveSuffix("podman.sock")) Expect(inspectInfo[0].ConnectionInfo.PodmanSocket.GetPath()).To(HaveSuffix("podman.sock"))

View File

@ -3,7 +3,7 @@ package e2e_test
import ( import (
"os" "os"
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine/define"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec" . "github.com/onsi/gomega/gexec"
@ -24,7 +24,7 @@ var _ = Describe("podman machine proxy settings propagation", func() {
It("ssh to running machine and check proxy settings", func() { It("ssh to running machine and check proxy settings", func() {
// https://github.com/containers/podman/issues/20129 // https://github.com/containers/podman/issues/20129
if testProvider.VMType() == machine.HyperVVirt { if testProvider.VMType() == define.HyperVVirt {
Skip("proxy settings not yet supported") Skip("proxy settings not yet supported")
} }
name := randomString() name := randomString()

View File

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine/define"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec" . "github.com/onsi/gomega/gexec"
@ -120,7 +120,7 @@ var _ = Describe("podman machine rm", func() {
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
// WSL does not use ignition // WSL does not use ignition
if testProvider.VMType() != machine.WSLVirt { if testProvider.VMType() != define.WSLVirt {
_, err = os.Stat(ign) _, err = os.Stat(ign)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
} }

View File

@ -6,7 +6,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine/define"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec" . "github.com/onsi/gomega/gexec"
@ -76,7 +76,7 @@ var _ = Describe("podman machine set", func() {
}) })
It("wsl cannot change disk, memory, processor", func() { It("wsl cannot change disk, memory, processor", func() {
skipIfNotVmtype(machine.WSLVirt, "tests are only for WSL provider") skipIfNotVmtype(define.WSLVirt, "tests are only for WSL provider")
name := randomString() name := randomString()
i := new(initMachine) i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run() session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run()
@ -168,7 +168,7 @@ var _ = Describe("podman machine set", func() {
}) })
It("set user mode networking", func() { It("set user mode networking", func() {
if testProvider.VMType() != machine.WSLVirt { if testProvider.VMType() != define.WSLVirt {
Skip("Test is only for WSL") Skip("Test is only for WSL")
} }
name := randomString() name := randomString()

View File

@ -1,7 +1,7 @@
package e2e_test package e2e_test
import ( import (
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine/define"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec" . "github.com/onsi/gomega/gexec"
@ -44,7 +44,7 @@ var _ = Describe("podman machine ssh", func() {
}) })
It("ssh to running machine and check os-type", func() { It("ssh to running machine and check os-type", func() {
wsl := testProvider.VMType() == machine.WSLVirt wsl := testProvider.VMType() == define.WSLVirt
name := randomString() name := randomString()
i := new(initMachine) i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withNow()).run() session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withNow()).run()

View File

@ -15,6 +15,7 @@ import (
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/compression" "github.com/containers/podman/v4/pkg/machine/compression"
"github.com/containers/podman/v4/pkg/machine/define" "github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/machine/ignition"
"github.com/docker/go-units" "github.com/docker/go-units"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -97,7 +98,7 @@ func (v HyperVVirtualization) List(opts machine.ListOptions) ([]*machine.ListRes
Running: vm.State() == hypervctl.Enabled, Running: vm.State() == hypervctl.Enabled,
Starting: mm.isStarting(), Starting: mm.isStarting(),
Stream: mm.ImageStream, Stream: mm.ImageStream,
VMType: machine.HyperVVirt.String(), VMType: define.HyperVVirt.String(),
CPUs: mm.CPUs, CPUs: mm.CPUs,
Memory: mm.Memory * units.MiB, Memory: mm.Memory * units.MiB,
DiskSize: mm.DiskSize * units.GiB, DiskSize: mm.DiskSize * units.GiB,
@ -126,7 +127,7 @@ func (v HyperVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM,
m.RemoteUsername = opts.Username m.RemoteUsername = opts.Username
configDir, err := machine.GetConfDir(machine.HyperVVirt) configDir, err := machine.GetConfDir(define.HyperVVirt)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -138,14 +139,14 @@ func (v HyperVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM,
m.ConfigPath = *configPath m.ConfigPath = *configPath
if err := machine.SetIgnitionFile(&m.IgnitionFile, vmtype, m.Name); err != nil { if err := ignition.SetIgnitionFile(&m.IgnitionFile, vmtype, m.Name, configDir); err != nil {
return nil, err return nil, err
} }
// Set creation time // Set creation time
m.Created = time.Now() m.Created = time.Now()
dataDir, err := machine.GetDataDir(machine.HyperVVirt) dataDir, err := machine.GetDataDir(define.HyperVVirt)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -250,7 +251,7 @@ func (v HyperVVirtualization) RemoveAndCleanMachines() error {
return prevErr return prevErr
} }
func (v HyperVVirtualization) VMType() machine.VMType { func (v HyperVVirtualization) VMType() define.VMType {
return vmtype return vmtype
} }

View File

@ -22,7 +22,9 @@ import (
"github.com/containers/podman/v4/pkg/machine/define" "github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/machine/hyperv/vsock" "github.com/containers/podman/v4/pkg/machine/hyperv/vsock"
"github.com/containers/podman/v4/pkg/machine/vmconfigs" "github.com/containers/podman/v4/pkg/machine/vmconfigs"
"github.com/containers/podman/v4/pkg/machine/ignition"
"github.com/containers/podman/v4/pkg/strongunits" "github.com/containers/podman/v4/pkg/strongunits"
"github.com/containers/podman/v4/pkg/systemd/parser"
"github.com/containers/podman/v4/pkg/util" "github.com/containers/podman/v4/pkg/util"
"github.com/containers/podman/v4/utils" "github.com/containers/podman/v4/utils"
"github.com/containers/storage/pkg/lockfile" "github.com/containers/storage/pkg/lockfile"
@ -32,7 +34,7 @@ import (
var ( var (
// vmtype refers to qemu (vs libvirt, krun, etc). // vmtype refers to qemu (vs libvirt, krun, etc).
vmtype = machine.HyperVVirt vmtype = define.HyperVVirt
) )
const ( const (
@ -45,40 +47,6 @@ const (
apiUpTimeout = 20 * time.Second apiUpTimeout = 20 * time.Second
) )
// hyperVReadyUnit is a unit file that sets up the virtual serial device
// where when the VM is done configuring, it will send an ack
// so a listening host knows it can begin interacting with it
//
// VSOCK-CONNECT:2 <- shortcut to connect to the hostvm
const hyperVReadyUnit = `[Unit]
After=remove-moby.service sshd.socket sshd.service
After=systemd-user-sessions.service
OnFailure=emergency.target
OnFailureJobMode=isolate
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/sh -c '/usr/bin/echo Ready | socat - VSOCK-CONNECT:2:%d'
[Install]
RequiredBy=default.target
`
// hyperVVsockNetUnit is a systemd unit file that calls the vm helper utility
// needed to take traffic from a network vsock0 device to the actual vsock
// and onto the host
const hyperVVsockNetUnit = `
[Unit]
Description=vsock_network
After=NetworkManager.service
[Service]
ExecStart=/usr/libexec/podman/gvforwarder -preexisting -iface vsock0 -url vsock://2:%d/connect
ExecStartPost=/usr/bin/nmcli c up vsock0
[Install]
WantedBy=multi-user.target
`
const hyperVVsockNMConnection = ` const hyperVVsockNMConnection = `
[connection] [connection]
id=vsock0 id=vsock0
@ -251,11 +219,11 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) {
} }
m.Rootful = opts.Rootful m.Rootful = opts.Rootful
builder := machine.NewIgnitionBuilder(machine.DynamicIgnition{ builder := ignition.NewIgnitionBuilder(ignition.DynamicIgnition{
Name: m.RemoteUsername, Name: m.RemoteUsername,
Key: key, Key: key,
VMName: m.Name, VMName: m.Name,
VMType: machine.HyperVVirt, VMType: define.HyperVVirt,
TimeZone: opts.TimeZone, TimeZone: opts.TimeZone,
WritePath: m.IgnitionFile.GetPath(), WritePath: m.IgnitionFile.GetPath(),
UID: m.UID, UID: m.UID,
@ -277,28 +245,38 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) {
return false, err return false, err
} }
builder.WithUnit(machine.Unit{ readyUnitFile, err := createReadyUnit(m.ReadyHVSock.Port)
Enabled: machine.BoolToPtr(true), if err != nil {
return false, err
}
builder.WithUnit(ignition.Unit{
Enabled: ignition.BoolToPtr(true),
Name: "ready.service", Name: "ready.service",
Contents: machine.StrToPtr(fmt.Sprintf(hyperVReadyUnit, m.ReadyHVSock.Port)), Contents: ignition.StrToPtr(readyUnitFile),
}) })
builder.WithUnit(machine.Unit{ netUnitFile, err := createNetworkUnit(m.NetworkHVSock.Port)
Contents: machine.StrToPtr(fmt.Sprintf(hyperVVsockNetUnit, m.NetworkHVSock.Port)), if err != nil {
Enabled: machine.BoolToPtr(true), return false, err
}
builder.WithUnit(ignition.Unit{
Contents: ignition.StrToPtr(netUnitFile),
Enabled: ignition.BoolToPtr(true),
Name: "vsock-network.service", Name: "vsock-network.service",
}) })
builder.WithFile(machine.File{ builder.WithFile(ignition.File{
Node: machine.Node{ Node: ignition.Node{
Path: "/etc/NetworkManager/system-connections/vsock0.nmconnection", Path: "/etc/NetworkManager/system-connections/vsock0.nmconnection",
}, },
FileEmbedded1: machine.FileEmbedded1{ FileEmbedded1: ignition.FileEmbedded1{
Append: nil, Append: nil,
Contents: machine.Resource{ Contents: ignition.Resource{
Source: machine.EncodeDataURLPtr(hyperVVsockNMConnection), Source: ignition.EncodeDataURLPtr(hyperVVsockNMConnection),
}, },
Mode: machine.IntToPtr(0600), Mode: ignition.IntToPtr(0600),
}, },
}) })
@ -315,6 +293,23 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) {
return err == nil, err return err == nil, err
} }
func createReadyUnit(readyPort uint64) (string, error) {
readyUnit := ignition.DefaultReadyUnitFile()
readyUnit.Add("Unit", "After", "systemd-user-sessions.service")
readyUnit.Add("Service", "ExecStart", fmt.Sprintf("/bin/sh -c '/usr/bin/echo Ready | socat - VSOCK-CONNECT:2:%d'", readyPort))
return readyUnit.ToString()
}
func createNetworkUnit(netPort uint64) (string, error) {
netUnit := parser.NewUnitFile()
netUnit.Add("Unit", "Description", "vsock_network")
netUnit.Add("Unit", "After", "NetworkManager.service")
netUnit.Add("Service", "ExecStart", fmt.Sprintf("/usr/libexec/podman/gvforwarder -preexisting -iface vsock0 -url vsock://2:%d/connect", netPort))
netUnit.Add("Service", "ExecStartPost", "/usr/bin/nmcli c up vsock0")
netUnit.Add("Install", "WantedBy", "multi-user.target")
return netUnit.ToString()
}
func (m *HyperVMachine) unregisterMachine() error { func (m *HyperVMachine) unregisterMachine() error {
vmm := hypervctl.NewVirtualMachineManager() vmm := hypervctl.NewVirtualMachineManager()
vm, err := vmm.GetMachine(m.Name) vm, err := vmm.GetMachine(m.Name)
@ -679,7 +674,7 @@ func (m *HyperVMachine) Stop(name string, opts machine.StopOptions) error {
} }
func (m *HyperVMachine) jsonConfigPath() (string, error) { func (m *HyperVMachine) jsonConfigPath() (string, error) {
configDir, err := machine.GetConfDir(machine.HyperVVirt) configDir, err := machine.GetConfDir(define.HyperVVirt)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -836,7 +831,7 @@ func (m *HyperVMachine) startHostNetworking() (int32, string, machine.APIForward
} }
func logCommandToFile(c *exec.Cmd, filename string) error { func logCommandToFile(c *exec.Cmd, filename string) error {
dir, err := machine.GetDataDir(machine.HyperVVirt) dir, err := machine.GetDataDir(define.HyperVVirt)
if err != nil { if err != nil {
return fmt.Errorf("obtain machine dir: %w", err) return fmt.Errorf("obtain machine dir: %w", err)
} }
@ -877,7 +872,7 @@ func (m *HyperVMachine) setupAPIForwarding(cmd gvproxy.GvproxyCommand) (gvproxy.
} }
func (m *HyperVMachine) dockerSock() (string, error) { func (m *HyperVMachine) dockerSock() (string, error) {
dd, err := machine.GetDataDir(machine.HyperVVirt) dd, err := machine.GetDataDir(define.HyperVVirt)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -886,7 +881,7 @@ func (m *HyperVMachine) dockerSock() (string, error) {
func (m *HyperVMachine) forwardSocketPath() (*define.VMFile, error) { func (m *HyperVMachine) forwardSocketPath() (*define.VMFile, error) {
sockName := "podman.sock" sockName := "podman.sock"
path, err := machine.GetDataDir(machine.HyperVVirt) path, err := machine.GetDataDir(define.HyperVVirt)
if err != nil { if err != nil {
return nil, fmt.Errorf("Resolving data dir: %s", err.Error()) return nil, fmt.Errorf("Resolving data dir: %s", err.Error())
} }

View File

@ -1,6 +1,6 @@
//go:build amd64 || arm64 //go:build amd64 || arm64
package machine package ignition
import ( import (
"encoding/json" "encoding/json"
@ -11,6 +11,7 @@ import (
"path/filepath" "path/filepath"
"github.com/containers/podman/v4/pkg/machine/define" "github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/systemd/parser"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -25,6 +26,7 @@ import (
const ( const (
PodmanDockerTmpConfPath = "/etc/tmpfiles.d/podman-docker.conf" PodmanDockerTmpConfPath = "/etc/tmpfiles.d/podman-docker.conf"
DefaultIgnitionUserName = "core"
) )
// Convenience function to convert int to ptr // Convenience function to convert int to ptr
@ -56,7 +58,7 @@ type DynamicIgnition struct {
TimeZone string TimeZone string
UID int UID int
VMName string VMName string
VMType VMType VMType define.VMType
WritePath string WritePath string
Cfg Config Cfg Config
Rootful bool Rootful bool
@ -133,23 +135,24 @@ func (ign *DynamicIgnition) GenerateIgnitionConfig() error {
ignStorage.Links = append(ignStorage.Links, tzLink) ignStorage.Links = append(ignStorage.Links, tzLink)
} }
deMoby := `[Unit] deMoby := parser.NewUnitFile()
Description=Remove moby-engine deMoby.Add("Unit", "Description", "Remove moby-engine")
# Run once for the machine deMoby.Add("Unit", "After", "systemd-machine-id-commit.service")
After=systemd-machine-id-commit.service deMoby.Add("Unit", "Before", "zincati.service")
Before=zincati.service deMoby.Add("Unit", "ConditionPathExists", "!/var/lib/%N.stamp")
ConditionPathExists=!/var/lib/%N.stamp
[Service] deMoby.Add("Service", "Type", "oneshot")
Type=oneshot deMoby.Add("Service", "RemainAfterExit", "yes")
RemainAfterExit=yes deMoby.Add("Service", "ExecStart", "/usr/bin/rpm-ostree override remove moby-engine")
ExecStart=/usr/bin/rpm-ostree override remove moby-engine deMoby.Add("Service", "ExecStart", "/usr/bin/rpm-ostree ex apply-live --allow-replacement")
ExecStart=/usr/bin/rpm-ostree ex apply-live --allow-replacement deMoby.Add("Service", "ExecStartPost", "/bin/touch /var/lib/%N.stamp")
ExecStartPost=/bin/touch /var/lib/%N.stamp
deMoby.Add("Install", "WantedBy", "default.target")
deMobyFile, err := deMoby.ToString()
if err != nil {
return err
}
[Install]
WantedBy=default.target
`
// This service gets environment variables that are provided // This service gets environment variables that are provided
// through qemu fw_cfg and then sets them into systemd/system.conf.d, // through qemu fw_cfg and then sets them into systemd/system.conf.d,
// profile.d and environment.d files // profile.d and environment.d files
@ -157,34 +160,39 @@ WantedBy=default.target
// Currently, it is used for propagating // Currently, it is used for propagating
// proxy settings e.g. HTTP_PROXY and others, on a start avoiding // proxy settings e.g. HTTP_PROXY and others, on a start avoiding
// a need of re-creating/re-initiating a VM // a need of re-creating/re-initiating a VM
envset := `[Unit]
Description=Environment setter from QEMU FW_CFG envset := parser.NewUnitFile()
[Service] envset.Add("Unit", "Description", "Environment setter from QEMU FW_CFG")
Type=oneshot
RemainAfterExit=yes envset.Add("Service", "Type", "oneshot")
Environment=FWCFGRAW=/sys/firmware/qemu_fw_cfg/by_name/opt/com.coreos/environment/raw envset.Add("Service", "RemainAfterExit", "yes")
Environment=SYSTEMD_CONF=/etc/systemd/system.conf.d/default-env.conf envset.Add("Service", "Environment", "FWCFGRAW=/sys/firmware/qemu_fw_cfg/by_name/opt/com.coreos/environment/raw")
Environment=ENVD_CONF=/etc/environment.d/default-env.conf envset.Add("Service", "Environment", "SYSTEMD_CONF=/etc/systemd/system.conf.d/default-env.conf")
Environment=PROFILE_CONF=/etc/profile.d/default-env.sh envset.Add("Service", "Environment", "ENVD_CONF=/etc/environment.d/default-env.conf")
ExecStart=/usr/bin/bash -c '/usr/bin/test -f ${FWCFGRAW} &&\ envset.Add("Service", "Environment", "PROFILE_CONF=/etc/profile.d/default-env.sh")
echo "[Manager]\n#Got from QEMU FW_CFG\nDefaultEnvironment=$(/usr/bin/base64 -d ${FWCFGRAW} | sed -e "s+|+ +g")\n" > ${SYSTEMD_CONF} ||\ envset.Add("Service", "ExecStart", `/usr/bin/bash -c '/usr/bin/test -f ${FWCFGRAW} &&\
echo "[Manager]\n#Got nothing from QEMU FW_CFG\n#DefaultEnvironment=\n" > ${SYSTEMD_CONF}' echo "[Manager]\n#Got from QEMU FW_CFG\nDefaultEnvironment=$(/usr/bin/base64 -d ${FWCFGRAW} | sed -e "s+|+ +g")\n" > ${SYSTEMD_CONF} ||\
ExecStart=/usr/bin/bash -c '/usr/bin/test -f ${FWCFGRAW} && (\ echo "[Manager]\n#Got nothing from QEMU FW_CFG\n#DefaultEnvironment=\n" > ${SYSTEMD_CONF}'`)
echo "#Got from QEMU FW_CFG"> ${ENVD_CONF};\ envset.Add("Service", "ExecStart", `/usr/bin/bash -c '/usr/bin/test -f ${FWCFGRAW} && (\
IFS="|";\ echo "#Got from QEMU FW_CFG"> ${ENVD_CONF};\
for iprxy in $(/usr/bin/base64 -d ${FWCFGRAW}); do\ IFS="|";\
echo "$iprxy" >> ${ENVD_CONF}; done ) || \ for iprxy in $(/usr/bin/base64 -d ${FWCFGRAW}); do\
echo "#Got nothing from QEMU FW_CFG"> ${ENVD_CONF}' echo "$iprxy" >> ${ENVD_CONF}; done ) || \
ExecStart=/usr/bin/bash -c '/usr/bin/test -f ${FWCFGRAW} && (\ echo "#Got nothing from QEMU FW_CFG"> ${ENVD_CONF}'`)
echo "#Got from QEMU FW_CFG"> ${PROFILE_CONF};\ envset.Add("Service", "ExecStart", `/usr/bin/bash -c '/usr/bin/test -f ${FWCFGRAW} && (\
IFS="|";\ echo "#Got from QEMU FW_CFG"> ${PROFILE_CONF};\
for iprxy in $(/usr/bin/base64 -d ${FWCFGRAW}); do\ IFS="|";\
echo "export $iprxy" >> ${PROFILE_CONF}; done ) || \ for iprxy in $(/usr/bin/base64 -d ${FWCFGRAW}); do\
echo "#Got nothing from QEMU FW_CFG"> ${PROFILE_CONF}' echo "export $iprxy" >> ${PROFILE_CONF}; done ) || \
ExecStartPost=/usr/bin/systemctl daemon-reload echo "#Got nothing from QEMU FW_CFG"> ${PROFILE_CONF}'`)
[Install] envset.Add("Service", "ExecStartPost", "/usr/bin/systemctl daemon-reload")
WantedBy=sysinit.target
` envset.Add("Install", "WantedBy", "sysinit.target")
envsetFile, err := envset.ToString()
if err != nil {
return err
}
ignSystemd := Systemd{ ignSystemd := Systemd{
Units: []Unit{ Units: []Unit{
{ {
@ -204,7 +212,7 @@ WantedBy=sysinit.target
{ {
Enabled: BoolToPtr(true), Enabled: BoolToPtr(true),
Name: "remove-moby.service", Name: "remove-moby.service",
Contents: &deMoby, Contents: &deMobyFile,
}, },
{ {
// Disable auto-updating of fcos images // Disable auto-updating of fcos images
@ -215,11 +223,11 @@ WantedBy=sysinit.target
}} }}
// Only qemu has the qemu firmware environment setting // Only qemu has the qemu firmware environment setting
if ign.VMType == QemuVirt { if ign.VMType == define.QemuVirt {
qemuUnit := Unit{ qemuUnit := Unit{
Enabled: BoolToPtr(true), Enabled: BoolToPtr(true),
Name: "envset-fwcfg.service", Name: "envset-fwcfg.service",
Contents: &envset, Contents: &envsetFile,
} }
ignSystemd.Units = append(ignSystemd.Units, qemuUnit) ignSystemd.Units = append(ignSystemd.Units, qemuUnit)
} }
@ -295,16 +303,19 @@ func getDirs(usrName string) []Directory {
return dirs return dirs
} }
func getFiles(usrName string, uid int, rootful bool, vmtype VMType) []File { func getFiles(usrName string, uid int, rootful bool, vmtype define.VMType) []File {
files := make([]File, 0) files := make([]File, 0)
lingerExample := `[Unit] lingerExample := parser.NewUnitFile()
Description=A systemd user unit demo lingerExample.Add("Unit", "Description", "A systemd user unit demo")
After=network-online.target lingerExample.Add("Unit", "After", "network-online.target")
Wants=network-online.target podman.socket lingerExample.Add("Unit", "Wants", "network-online.target podman.socket")
[Service] lingerExample.Add("Service", "ExecStart", "/usr/bin/sleep infinity")
ExecStart=/usr/bin/sleep infinity lingerExampleFile, err := lingerExample.ToString()
` if err != nil {
logrus.Warnf(err.Error())
}
containers := `[containers] containers := `[containers]
netns="bridge" netns="bridge"
` `
@ -335,7 +346,7 @@ Delegate=memory pids cpu io
FileEmbedded1: FileEmbedded1{ FileEmbedded1: FileEmbedded1{
Append: nil, Append: nil,
Contents: Resource{ Contents: Resource{
Source: EncodeDataURLPtr(lingerExample), Source: EncodeDataURLPtr(lingerExampleFile),
}, },
Mode: IntToPtr(0744), Mode: IntToPtr(0744),
}, },
@ -676,12 +687,7 @@ func GetPodmanDockerTmpConfig(uid int, rootful bool, newline bool) string {
// SetIgnitionFile creates a new Machine File for the machine's ignition file // SetIgnitionFile creates a new Machine File for the machine's ignition file
// and assignes the handle to `loc` // and assignes the handle to `loc`
func SetIgnitionFile(loc *define.VMFile, vmtype VMType, vmName string) error { func SetIgnitionFile(loc *define.VMFile, vmtype define.VMType, vmName, vmConfigDir string) error {
vmConfigDir, err := GetConfDir(vmtype)
if err != nil {
return err
}
ignitionFile, err := define.NewMachineFile(filepath.Join(vmConfigDir, vmName+".ign"), nil) ignitionFile, err := define.NewMachineFile(filepath.Join(vmConfigDir, vmName+".ign"), nil)
if err != nil { if err != nil {
return err return err
@ -735,3 +741,14 @@ func (i *IgnitionBuilder) BuildWithIgnitionFile(ignPath string) error {
func (i *IgnitionBuilder) Build() error { func (i *IgnitionBuilder) Build() error {
return i.dynamicIgnition.Write() return i.dynamicIgnition.Write()
} }
func DefaultReadyUnitFile() parser.UnitFile {
u := parser.NewUnitFile()
u.Add("Unit", "After", "remove-moby.service sshd.socket sshd.service")
u.Add("Unit", "OnFailure", "emergency.target")
u.Add("Unit", "OnFailureJobMode", "isolate")
u.Add("Service", "Type", "oneshot")
u.Add("Service", "RemainAfterExit", "yes")
u.Add("Install", "RequiredBy", "default.target")
return *u
}

View File

@ -1,6 +1,6 @@
//go:build darwin //go:build darwin
package machine package ignition
import ( import (
"os" "os"

View File

@ -1,6 +1,6 @@
//go:build freebsd //go:build freebsd
package machine package ignition
func getLocalTimeZone() (string, error) { func getLocalTimeZone() (string, error) {
return "", nil return "", nil

View File

@ -1,4 +1,4 @@
package machine package ignition
import ( import (
"errors" "errors"

View File

@ -1,6 +1,6 @@
//go:build amd64 || arm64 //go:build amd64 || arm64
package machine package ignition
/* /*
This file was taken from https://github.com/coreos/ignition/blob/master/config/v3_2/types/schema.go in an effort to This file was taken from https://github.com/coreos/ignition/blob/master/config/v3_2/types/schema.go in an effort to

View File

@ -1,6 +1,6 @@
//go:build windows //go:build windows
package machine package ignition
func getLocalTimeZone() (string, error) { func getLocalTimeZone() (string, error) {
return "", nil return "", nil

View File

@ -8,6 +8,7 @@ import (
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/machine/qemu" "github.com/containers/podman/v4/pkg/machine/qemu"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -21,14 +22,14 @@ func Get() (machine.VirtProvider, error) {
if providerOverride, found := os.LookupEnv("CONTAINERS_MACHINE_PROVIDER"); found { if providerOverride, found := os.LookupEnv("CONTAINERS_MACHINE_PROVIDER"); found {
provider = providerOverride provider = providerOverride
} }
resolvedVMType, err := machine.ParseVMType(provider, machine.QemuVirt) resolvedVMType, err := define.ParseVMType(provider, define.QemuVirt)
if err != nil { if err != nil {
return nil, err return nil, err
} }
logrus.Debugf("Using Podman machine with `%s` virtualization provider", resolvedVMType.String()) logrus.Debugf("Using Podman machine with `%s` virtualization provider", resolvedVMType.String())
switch resolvedVMType { switch resolvedVMType {
case machine.QemuVirt: case define.QemuVirt:
return qemu.VirtualizationProvider(), nil return qemu.VirtualizationProvider(), nil
default: default:
return nil, fmt.Errorf("unsupported virtualization provider: `%s`", resolvedVMType.String()) return nil, fmt.Errorf("unsupported virtualization provider: `%s`", resolvedVMType.String())

View File

@ -7,6 +7,7 @@ import (
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/applehv" "github.com/containers/podman/v4/pkg/machine/applehv"
"github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/machine/qemu" "github.com/containers/podman/v4/pkg/machine/qemu"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -20,16 +21,16 @@ func Get() (machine.VirtProvider, error) {
if providerOverride, found := os.LookupEnv("CONTAINERS_MACHINE_PROVIDER"); found { if providerOverride, found := os.LookupEnv("CONTAINERS_MACHINE_PROVIDER"); found {
provider = providerOverride provider = providerOverride
} }
resolvedVMType, err := machine.ParseVMType(provider, machine.AppleHvVirt) resolvedVMType, err := define.ParseVMType(provider, define.AppleHvVirt)
if err != nil { if err != nil {
return nil, err return nil, err
} }
logrus.Debugf("Using Podman machine with `%s` virtualization provider", resolvedVMType.String()) logrus.Debugf("Using Podman machine with `%s` virtualization provider", resolvedVMType.String())
switch resolvedVMType { switch resolvedVMType {
case machine.QemuVirt: case define.QemuVirt:
return qemu.VirtualizationProvider(), nil return qemu.VirtualizationProvider(), nil
case machine.AppleHvVirt: case define.AppleHvVirt:
return applehv.VirtualizationProvider(), nil return applehv.VirtualizationProvider(), nil
default: default:
return nil, fmt.Errorf("unsupported virtualization provider: `%s`", resolvedVMType.String()) return nil, fmt.Errorf("unsupported virtualization provider: `%s`", resolvedVMType.String())

View File

@ -6,6 +6,7 @@ import (
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/machine/hyperv" "github.com/containers/podman/v4/pkg/machine/hyperv"
"github.com/containers/podman/v4/pkg/machine/wsl" "github.com/containers/podman/v4/pkg/machine/wsl"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -20,16 +21,16 @@ func Get() (machine.VirtProvider, error) {
if providerOverride, found := os.LookupEnv("CONTAINERS_MACHINE_PROVIDER"); found { if providerOverride, found := os.LookupEnv("CONTAINERS_MACHINE_PROVIDER"); found {
provider = providerOverride provider = providerOverride
} }
resolvedVMType, err := machine.ParseVMType(provider, machine.WSLVirt) resolvedVMType, err := define.ParseVMType(provider, define.WSLVirt)
if err != nil { if err != nil {
return nil, err return nil, err
} }
logrus.Debugf("Using Podman machine with `%s` virtualization provider", resolvedVMType.String()) logrus.Debugf("Using Podman machine with `%s` virtualization provider", resolvedVMType.String())
switch resolvedVMType { switch resolvedVMType {
case machine.WSLVirt: case define.WSLVirt:
return wsl.VirtualizationProvider(), nil return wsl.VirtualizationProvider(), nil
case machine.HyperVVirt: case define.HyperVVirt:
return hyperv.VirtualizationProvider(), nil return hyperv.VirtualizationProvider(), nil
default: default:
return nil, fmt.Errorf("unsupported virtualization provider: `%s`", resolvedVMType.String()) return nil, fmt.Errorf("unsupported virtualization provider: `%s`", resolvedVMType.String())

View File

@ -28,7 +28,7 @@ type GenericDownload struct {
} }
// NewGenericDownloader is used when the disk image is provided by the user // NewGenericDownloader is used when the disk image is provided by the user
func NewGenericDownloader(vmType VMType, vmName, pullPath string) (DistributionDownload, error) { func NewGenericDownloader(vmType define.VMType, vmName, pullPath string) (DistributionDownload, error) {
var ( var (
imageName string imageName string
) )

View File

@ -13,6 +13,7 @@ import (
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/compression" "github.com/containers/podman/v4/pkg/machine/compression"
"github.com/containers/podman/v4/pkg/machine/define" "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" "github.com/containers/podman/v4/pkg/machine/qemu/command"
"github.com/containers/podman/v4/pkg/machine/sockets" "github.com/containers/podman/v4/pkg/machine/sockets"
"github.com/containers/podman/v4/pkg/machine/vmconfigs" "github.com/containers/podman/v4/pkg/machine/vmconfigs"
@ -84,8 +85,13 @@ func (p *QEMUVirtualization) NewMachine(opts machine.InitOptions) (machine.VM, e
return nil, err return nil, err
} }
confDir, err := machine.GetConfDir(vmtype)
if err != nil {
return nil, err
}
// set VM ignition file // set VM ignition file
if err := machine.SetIgnitionFile(&vm.IgnitionFile, vmtype, vm.Name); err != nil { if err := ignition.SetIgnitionFile(&vm.IgnitionFile, vmtype, vm.Name, confDir); err != nil {
return nil, err return nil, err
} }
@ -330,7 +336,7 @@ func (p *QEMUVirtualization) RemoveAndCleanMachines() error {
return prevErr return prevErr
} }
func (p *QEMUVirtualization) VMType() machine.VMType { func (p *QEMUVirtualization) VMType() define.VMType {
return vmtype return vmtype
} }

View File

@ -23,6 +23,7 @@ import (
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types" gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define" "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" "github.com/containers/podman/v4/pkg/machine/qemu/command"
"github.com/containers/podman/v4/pkg/machine/sockets" "github.com/containers/podman/v4/pkg/machine/sockets"
"github.com/containers/podman/v4/pkg/machine/vmconfigs" "github.com/containers/podman/v4/pkg/machine/vmconfigs"
@ -36,7 +37,7 @@ import (
var ( var (
// vmtype refers to qemu (vs libvirt, krun, etc). // vmtype refers to qemu (vs libvirt, krun, etc).
// Could this be moved into Provider // Could this be moved into Provider
vmtype = machine.QemuVirt vmtype = define.QemuVirt
) )
const ( const (
@ -46,23 +47,6 @@ const (
dockerConnectTimeout = 5 * time.Second dockerConnectTimeout = 5 * time.Second
) )
// qemuReadyUnit is a unit file that sets up the virtual serial device
// where when the VM is done configuring, it will send an ack
// so a listening host tknows it can begin interacting with it
const qemuReadyUnit = `[Unit]
Requires=dev-virtio\\x2dports-%s.device
After=remove-moby.service sshd.socket sshd.service
After=systemd-user-sessions.service
OnFailure=emergency.target
OnFailureJobMode=isolate
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/sh -c '/usr/bin/echo Ready >/dev/%s'
[Install]
RequiredBy=default.target
`
type MachineVM struct { type MachineVM struct {
// ConfigPath is the path to the configuration file // ConfigPath is the path to the configuration file
ConfigPath define.VMFile ConfigPath define.VMFile
@ -208,11 +192,11 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
logrus.Warn("ignoring init option to disable user-mode networking: this mode is not supported by the QEMU backend") logrus.Warn("ignoring init option to disable user-mode networking: this mode is not supported by the QEMU backend")
} }
builder := machine.NewIgnitionBuilder(machine.DynamicIgnition{ builder := ignition.NewIgnitionBuilder(ignition.DynamicIgnition{
Name: opts.Username, Name: opts.Username,
Key: key, Key: key,
VMName: v.Name, VMName: v.Name,
VMType: machine.QemuVirt, VMType: define.QemuVirt,
TimeZone: opts.TimeZone, TimeZone: opts.TimeZone,
WritePath: v.getIgnitionFile(), WritePath: v.getIgnitionFile(),
UID: v.UID, UID: v.UID,
@ -229,10 +213,14 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
return false, err return false, err
} }
readyUnit := machine.Unit{ readyUnitFile, err := createReadyUnitFile()
Enabled: machine.BoolToPtr(true), if err != nil {
return false, err
}
readyUnit := ignition.Unit{
Enabled: ignition.BoolToPtr(true),
Name: "ready.service", Name: "ready.service",
Contents: machine.StrToPtr(fmt.Sprintf(qemuReadyUnit, "vport1p1", "vport1p1")), Contents: ignition.StrToPtr(readyUnitFile),
} }
builder.WithUnit(readyUnit) builder.WithUnit(readyUnit)
@ -242,6 +230,14 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
return err == nil, err return err == nil, err
} }
func createReadyUnitFile() (string, error) {
readyUnit := ignition.DefaultReadyUnitFile()
readyUnit.Add("Unit", "Requires", "dev-virtio\\x2dports-vport1p1.device")
readyUnit.Add("Unit", "After", "systemd-user-sessions.service")
readyUnit.Add("Service", "ExecStart", "/bin/sh -c '/usr/bin/echo Ready >/dev/vport1p1'")
return readyUnit.ToString()
}
func (v *MachineVM) removeSSHKeys() error { func (v *MachineVM) removeSSHKeys() error {
if err := os.Remove(fmt.Sprintf("%s.pub", v.IdentityPath)); err != nil { if err := os.Remove(fmt.Sprintf("%s.pub", v.IdentityPath)); err != nil {
logrus.Error(err) logrus.Error(err)
@ -1222,7 +1218,7 @@ func (v *MachineVM) isIncompatible() bool {
} }
func (v *MachineVM) userGlobalSocketLink() (string, error) { func (v *MachineVM) userGlobalSocketLink() (string, error) {
path, err := machine.GetDataDir(machine.QemuVirt) path, err := machine.GetDataDir(define.QemuVirt)
if err != nil { if err != nil {
logrus.Errorf("Resolving data dir: %s", err.Error()) logrus.Errorf("Resolving data dir: %s", err.Error())
return "", err return "", err
@ -1233,7 +1229,7 @@ func (v *MachineVM) userGlobalSocketLink() (string, error) {
func (v *MachineVM) forwardSocketPath() (*define.VMFile, error) { func (v *MachineVM) forwardSocketPath() (*define.VMFile, error) {
sockName := "podman.sock" sockName := "podman.sock"
path, err := machine.GetDataDir(machine.QemuVirt) path, err := machine.GetDataDir(define.QemuVirt)
if err != nil { if err != nil {
logrus.Errorf("Resolving data dir: %s", err.Error()) logrus.Errorf("Resolving data dir: %s", err.Error())
return nil, err return nil, err

View File

@ -5,12 +5,13 @@ package machine
import ( import (
"fmt" "fmt"
"github.com/containers/podman/v4/pkg/machine/ignition"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
func UpdatePodmanDockerSockService(vm VM, name string, uid int, rootful bool) error { func UpdatePodmanDockerSockService(vm VM, name string, uid int, rootful bool) error {
content := GetPodmanDockerTmpConfig(uid, rootful, false) content := ignition.GetPodmanDockerTmpConfig(uid, rootful, false)
command := fmt.Sprintf("'echo %q > %s'", content, PodmanDockerTmpConfPath) command := fmt.Sprintf("'echo %q > %s'", content, ignition.PodmanDockerTmpConfPath)
args := []string{"sudo", "bash", "-c", command} args := []string{"sudo", "bash", "-c", command}
if err := vm.SSH(name, SSHOptions{Args: args}); err != nil { if err := vm.SSH(name, SSHOptions{Args: args}); err != nil {
logrus.Warnf("Could not not update internal docker sock config") logrus.Warnf("Could not not update internal docker sock config")

View File

@ -230,6 +230,6 @@ func (p *WSLVirtualization) RemoveAndCleanMachines() error {
return prevErr return prevErr
} }
func (p *WSLVirtualization) VMType() machine.VMType { func (p *WSLVirtualization) VMType() define.VMType {
return vmtype return vmtype
} }

View File

@ -27,7 +27,7 @@ type FedoraDownload struct {
machine.Download machine.Download
} }
func NewFedoraDownloader(vmType machine.VMType, vmName, releaseStream string) (machine.DistributionDownload, error) { func NewFedoraDownloader(vmType define.VMType, vmName, releaseStream string) (machine.DistributionDownload, error) {
downloadURL, version, arch, size, err := getFedoraDownload() downloadURL, version, arch, size, err := getFedoraDownload()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -20,6 +20,7 @@ import (
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define" "github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/machine/vmconfigs" "github.com/containers/podman/v4/pkg/machine/vmconfigs"
"github.com/containers/podman/v4/pkg/machine/ignition"
"github.com/containers/podman/v4/pkg/machine/wsl/wutil" "github.com/containers/podman/v4/pkg/machine/wsl/wutil"
"github.com/containers/podman/v4/pkg/util" "github.com/containers/podman/v4/pkg/util"
"github.com/containers/podman/v4/utils" "github.com/containers/podman/v4/utils"
@ -32,7 +33,7 @@ import (
var ( var (
// vmtype refers to qemu (vs libvirt, krun, etc) // vmtype refers to qemu (vs libvirt, krun, etc)
vmtype = machine.WSLVirt vmtype = define.WSLVirt
) )
const ( const (
@ -717,9 +718,9 @@ func getBindMountFsTab(dist string) string {
} }
func (v *MachineVM) setupPodmanDockerSock(dist string, rootful bool) error { func (v *MachineVM) setupPodmanDockerSock(dist string, rootful bool) error {
content := machine.GetPodmanDockerTmpConfig(1000, rootful, true) content := ignition.GetPodmanDockerTmpConfig(1000, rootful, true)
if err := wslPipe(content, dist, "sh", "-c", "cat > "+machine.PodmanDockerTmpConfPath); err != nil { if err := wslPipe(content, dist, "sh", "-c", "cat > "+ignition.PodmanDockerTmpConfPath); err != nil {
return fmt.Errorf("could not create internal docker sock conf: %w", err) return fmt.Errorf("could not create internal docker sock conf: %w", err)
} }