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 {
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 {
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/libpod/events"
"github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define"
"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
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)
}

View File

@ -13,6 +13,7 @@ import (
"github.com/containers/podman/v4/pkg/machine/compression"
"github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/machine/vmconfigs"
"github.com/containers/podman/v4/pkg/machine/ignition"
vfConfig "github.com/crc-org/vfkit/pkg/config"
"github.com/docker/go-units"
"golang.org/x/sys/unix"
@ -55,7 +56,7 @@ func (v AppleHVVirtualization) CheckExclusiveActiveVM() (bool, string, error) {
}
func (v AppleHVVirtualization) IsValidVMName(name string) (bool, error) {
configDir, err := machine.GetConfDir(machine.AppleHvVirt)
configDir, err := machine.GetConfDir(define.AppleHvVirt)
if err != nil {
return false, err
}
@ -93,7 +94,7 @@ func (v AppleHVVirtualization) List(opts machine.ListOptions) ([]*machine.ListRe
Running: vmState == define.Running,
Starting: vmState == define.Starting,
Stream: mm.ImageStream,
VMType: machine.AppleHvVirt.String(),
VMType: define.AppleHvVirt.String(),
CPUs: mm.CPUs,
Memory: mm.Memory * units.MiB,
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")
}
configDir, err := machine.GetConfDir(machine.AppleHvVirt)
configDir, err := machine.GetConfDir(define.AppleHvVirt)
if err != nil {
return nil, err
}
@ -129,12 +130,12 @@ func (v AppleHVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM,
}
m.ConfigPath = *configPath
dataDir, err := machine.GetDataDir(machine.AppleHvVirt)
dataDir, err := machine.GetDataDir(define.AppleHvVirt)
if err != nil {
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
}
@ -161,7 +162,7 @@ func (v AppleHVVirtualization) RemoveAndCleanMachines() error {
return machine.ErrNotImplemented
}
func (v AppleHVVirtualization) VMType() machine.VMType {
func (v AppleHVVirtualization) VMType() define.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/sockets"
"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/systemd/parser"
"github.com/containers/podman/v4/pkg/util"
"github.com/containers/podman/v4/utils"
"github.com/containers/storage/pkg/lockfile"
@ -36,7 +38,7 @@ import (
var (
// vmtype refers to qemu (vs libvirt, krun, etc).
vmtype = machine.AppleHvVirt
vmtype = define.AppleHvVirt
)
const (
@ -45,21 +47,13 @@ const (
apiUpTimeout = 20 * time.Second
)
// appleHVReadyUnit 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
const appleHVReadyUnit = `[Unit]
Requires=dev-virtio\\x2dports-%s.device
After=remove-moby.service sshd.socket sshd.service
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
`
// VfkitHelper describes the use of vfkit: cmdline and endpoint
type VfkitHelper struct {
LogLevel logrus.Level
Endpoint string
VfkitBinaryPath *define.VMFile
VirtualMachine *vfConfig.VirtualMachine
}
type MacMachine struct {
// 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()
callbackFuncs.Add(m.ConfigPath.Delete)
dataDir, err := machine.GetDataDir(machine.AppleHvVirt)
dataDir, err := machine.GetDataDir(define.AppleHvVirt)
if err != nil {
return false, err
}
@ -254,11 +248,11 @@ func (m *MacMachine) Init(opts machine.InitOptions) (bool, error) {
callbackFuncs.Add(m.removeSSHKeys)
}
builder := machine.NewIgnitionBuilder(machine.DynamicIgnition{
builder := ignition.NewIgnitionBuilder(ignition.DynamicIgnition{
Name: opts.Username,
Key: key,
VMName: m.Name,
VMType: machine.AppleHvVirt,
VMType: define.AppleHvVirt,
TimeZone: opts.TimeZone,
WritePath: m.IgnitionFile.GetPath(),
UID: m.UID,
@ -273,10 +267,15 @@ func (m *MacMachine) Init(opts machine.InitOptions) (bool, error) {
return false, err
}
builder.WithUnit(machine.Unit{
Enabled: machine.BoolToPtr(true),
readyUnitFile, err := createReadyUnitFile()
if err != nil {
return false, err
}
builder.WithUnit(ignition.Unit{
Enabled: ignition.BoolToPtr(true),
Name: "ready.service",
Contents: machine.StrToPtr(fmt.Sprintf(appleHVReadyUnit, "vsock")),
Contents: ignition.StrToPtr(readyUnitFile),
})
builder.WithUnit(generateSystemDFilesForVirtiofsMounts(virtiofsMnts)...)
@ -287,6 +286,13 @@ func (m *MacMachine) Init(opts machine.InitOptions) (bool, error) {
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 {
if err := os.Remove(fmt.Sprintf("%s.pub", m.IdentityPath)); err != nil {
logrus.Error(err)
@ -786,7 +792,7 @@ func loadMacMachineFromJSON(fqConfigPath string) (*MacMachine, error) {
}
func (m *MacMachine) jsonConfigPath() (string, error) {
configDir, err := machine.GetConfDir(machine.AppleHvVirt)
configDir, err := machine.GetConfDir(define.AppleHvVirt)
if err != nil {
return "", err
}
@ -817,7 +823,7 @@ func getVMInfos() ([]*machine.ListResponse, error) {
listEntry.Name = vm.Name
listEntry.Stream = vm.ImageStream
listEntry.VMType = machine.AppleHvVirt.String()
listEntry.VMType = define.AppleHvVirt.String()
listEntry.CPUs = vm.CPUs
listEntry.Memory = vm.Memory * units.MiB
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) {
dd, err := machine.GetDataDir(machine.AppleHvVirt)
dd, err := machine.GetDataDir(define.AppleHvVirt)
if err != nil {
return "", err
}
@ -1023,7 +1029,7 @@ func (m *MacMachine) dockerSock() (string, error) {
func (m *MacMachine) forwardSocketPath() (*define.VMFile, error) {
sockName := "podman.sock"
path, err := machine.GetDataDir(machine.AppleHvVirt)
path, err := machine.GetDataDir(define.AppleHvVirt)
if err != nil {
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) {
dataDir, err := machine.GetDataDir(machine.AppleHvVirt)
dataDir, err := machine.GetDataDir(define.AppleHvVirt)
if err != nil {
return nil, err
}
@ -1087,7 +1093,7 @@ func (m *MacMachine) getRuntimeDir() (string, error) {
}
func (m *MacMachine) userGlobalSocketLink() (string, error) {
path, err := machine.GetDataDir(machine.AppleHvVirt)
path, err := machine.GetDataDir(define.AppleHvVirt)
if err != nil {
logrus.Errorf("Resolving data dir: %s", err.Error())
return "", err
@ -1100,46 +1106,49 @@ func (m *MacMachine) isIncompatible() bool {
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
// 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.
var unitFiles []machine.Unit
var unitFiles []ignition.Unit
for _, mnt := range mounts {
// 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
// on boot.
autoMountUnit := `[Automount]
Where=%s
[Install]
WantedBy=multi-user.target
[Unit]
Description=Mount virtiofs volume %s
`
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)),
autoMountUnit := parser.NewUnitFile()
autoMountUnit.Add("Automount", "Where", "%s")
autoMountUnit.Add("Install", "WantedBy", "multi-user.target")
autoMountUnit.Add("Unit", "Description", "Mount virtiofs volume %s")
autoMountUnitFile, err := autoMountUnit.ToString()
if err != nil {
logrus.Warnf(err.Error())
}
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),
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@
enablePrep := machine.Unit{
Enabled: machine.BoolToPtr(true),
enablePrep := ignition.Unit{
Enabled: ignition.BoolToPtr(true),
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
// at the rootfs / and then mounting to them.
mountPrep := `
[Unit]
Description=Allow virtios to mount to /
DefaultDependencies=no
ConditionPathExists=!%f
mountPrep := parser.NewUnitFile()
mountPrep.Add("Unit", "Description", "Allow virtios to mount to /")
mountPrep.Add("Unit", "DefaultDependencies", "no")
mountPrep.Add("Unit", "ConditionPathExists", "!%f")
[Service]
Type=oneshot
ExecStartPre=chattr -i /
ExecStart=mkdir -p '%f'
ExecStopPost=chattr +i /
mountPrep.Add("Service", "Type", "oneshot")
mountPrep.Add("Service", "ExecStartPre", "chattr -i /")
mountPrep.Add("Service", "ExecStart", "mkdir -p '%f'")
mountPrep.Add("Service", "ExecStopPost", "chattr +i /")
[Install]
WantedBy=remote-fs.target
`
virtioFSChattr := machine.Unit{
Contents: machine.StrToPtr(mountPrep),
mountPrep.Add("Install", "WantedBy", "remote-fs.target")
mountPrepFile, err := mountPrep.ToString()
if err != nil {
logrus.Warnf(err.Error())
}
virtioFSChattr := ignition.Unit{
Contents: ignition.StrToPtr(mountPrepFile),
Name: "virtiofs-mount-prepare@.service",
}
unitFiles = append(unitFiles, virtioFSChattr)

View File

@ -14,7 +14,6 @@ import (
"strings"
"time"
"github.com/containers/common/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/compression"
"github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/machine/vmconfigs"
@ -51,9 +50,8 @@ const (
type RemoteConnectionType string
var (
SSHRemoteConnection RemoteConnectionType = "ssh"
DefaultIgnitionUserName = "core"
ForwarderBinaryName = "gvproxy"
SSHRemoteConnection RemoteConnectionType = "ssh"
ForwarderBinaryName = "gvproxy"
)
type Download struct {
@ -69,7 +67,7 @@ type Download struct {
Sha256sum string
Size int64
URL *url.URL
VMKind VMType
VMKind define.VMType
VMName string
}
@ -133,7 +131,7 @@ type VM interface {
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
// across the code base. This should be done once and stored
// 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
func GetCacheDir(vmType VMType) (string, error) {
func GetCacheDir(vmType define.VMType) (string, error) {
dataDir, err := GetDataDir(vmType)
if err != nil {
return "", err
@ -205,7 +203,7 @@ func GetCacheDir(vmType VMType) (string, error) {
// GetDataDir returns the filepath where vm images should
// live for podman-machine.
func GetDataDir(vmType VMType) (string, error) {
func GetDataDir(vmType define.VMType) (string, error) {
dataDirPrefix, err := DataDirPrefix()
if err != nil {
return "", err
@ -241,7 +239,7 @@ func DataDirPrefix() (string, error) {
// GetConfigDir returns the filepath to where configuration
// files for podman-machine should live
func GetConfDir(vmType VMType) (string, error) {
func GetConfDir(vmType define.VMType) (string, error) {
confDirPrefix, err := ConfDirPrefix()
if err != nil {
return "", err
@ -283,28 +281,6 @@ type ConnectionConfig struct {
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
const (
@ -315,23 +291,6 @@ const (
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
Artifact() define.Artifact
CheckExclusiveActiveVM() (bool, string, error)
@ -343,14 +302,14 @@ type VirtProvider interface { //nolint:interfacebloat
NewMachine(opts InitOptions) (VM, error)
NewDownload(vmName string) (Download, error)
RemoveAndCleanMachines() error
VMType() VMType
VMType() define.VMType
}
type Virtualization struct {
artifact define.Artifact
compression compression.ImageCompression
format define.ImageFormat
vmKind VMType
vmKind define.VMType
}
func (p *Virtualization) Artifact() define.Artifact {
@ -365,7 +324,7 @@ func (p *Virtualization) Format() define.ImageFormat {
return p.format
}
func (p *Virtualization) VMType() VMType {
func (p *Virtualization) VMType() define.VMType {
return p.vmKind
}
@ -391,7 +350,7 @@ func (p *Virtualization) NewDownload(vmName string) (Download, error) {
}, 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{
artifact,
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"
"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/storage/pkg/stringid"
. "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")
}
func skipIfVmtype(vmType machine.VMType, message string) {
func skipIfVmtype(vmType define.VMType, message string) {
if isVmtype(vmType) {
Skip(message)
}
}
func skipIfNotVmtype(vmType machine.VMType, message string) {
func skipIfNotVmtype(vmType define.VMType, message string) {
if !isVmtype(vmType) {
Skip(message)
}
}
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
}
// isWSL is a simple wrapper to determine if the testprovider is WSL
func isWSL() bool {
return isVmtype(machine.WSLVirt)
return isVmtype(define.WSLVirt)
}
func getFCOSDownloadLocation(p machine.VirtProvider) string {

View File

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

View File

@ -8,7 +8,6 @@ import (
"strings"
"time"
"github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/utils"
. "github.com/onsi/ginkgo/v2"
@ -80,7 +79,7 @@ var _ = Describe("podman machine init", func() {
testMachine := inspectBefore[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.Memory).To(Equal(uint64(2048)))
}
@ -136,7 +135,7 @@ var _ = Describe("podman machine init", func() {
Expect(inspectBefore).ToNot(BeEmpty())
testMachine := inspectBefore[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.Memory).To(Equal(uint64(2048)))
}
@ -186,7 +185,7 @@ var _ = Describe("podman machine init", 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")
}
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() {
if testProvider.VMType() != machine.WSLVirt {
if testProvider.VMType() != define.WSLVirt {
Skip("test is only supported by WSL")
}
i := new(initMachine)
@ -327,7 +326,7 @@ var _ = Describe("podman machine init", func() {
Expect(err).To(HaveOccurred())
// WSL does not use ignition
if testProvider.VMType() != machine.WSLVirt {
if testProvider.VMType() != define.WSLVirt {
_, err = os.Stat(ign)
Expect(err).To(HaveOccurred())
}

View File

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

View File

@ -3,7 +3,7 @@ package e2e_test
import (
"os"
"github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
. "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() {
// https://github.com/containers/podman/issues/20129
if testProvider.VMType() == machine.HyperVVirt {
if testProvider.VMType() == define.HyperVVirt {
Skip("proxy settings not yet supported")
}
name := randomString()

View File

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

View File

@ -6,7 +6,7 @@ import (
"strconv"
"strings"
"github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec"
@ -76,7 +76,7 @@ var _ = Describe("podman machine set", 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()
i := new(initMachine)
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() {
if testProvider.VMType() != machine.WSLVirt {
if testProvider.VMType() != define.WSLVirt {
Skip("Test is only for WSL")
}
name := randomString()

View File

@ -1,7 +1,7 @@
package e2e_test
import (
"github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
. "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() {
wsl := testProvider.VMType() == machine.WSLVirt
wsl := testProvider.VMType() == define.WSLVirt
name := randomString()
i := new(initMachine)
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/compression"
"github.com/containers/podman/v4/pkg/machine/define"
"github.com/containers/podman/v4/pkg/machine/ignition"
"github.com/docker/go-units"
"github.com/sirupsen/logrus"
)
@ -97,7 +98,7 @@ func (v HyperVVirtualization) List(opts machine.ListOptions) ([]*machine.ListRes
Running: vm.State() == hypervctl.Enabled,
Starting: mm.isStarting(),
Stream: mm.ImageStream,
VMType: machine.HyperVVirt.String(),
VMType: define.HyperVVirt.String(),
CPUs: mm.CPUs,
Memory: mm.Memory * units.MiB,
DiskSize: mm.DiskSize * units.GiB,
@ -126,7 +127,7 @@ func (v HyperVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM,
m.RemoteUsername = opts.Username
configDir, err := machine.GetConfDir(machine.HyperVVirt)
configDir, err := machine.GetConfDir(define.HyperVVirt)
if err != nil {
return nil, err
}
@ -138,14 +139,14 @@ func (v HyperVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM,
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
}
// Set creation time
m.Created = time.Now()
dataDir, err := machine.GetDataDir(machine.HyperVVirt)
dataDir, err := machine.GetDataDir(define.HyperVVirt)
if err != nil {
return nil, err
}
@ -250,7 +251,7 @@ func (v HyperVVirtualization) RemoveAndCleanMachines() error {
return prevErr
}
func (v HyperVVirtualization) VMType() machine.VMType {
func (v HyperVVirtualization) VMType() define.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/hyperv/vsock"
"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/systemd/parser"
"github.com/containers/podman/v4/pkg/util"
"github.com/containers/podman/v4/utils"
"github.com/containers/storage/pkg/lockfile"
@ -32,7 +34,7 @@ import (
var (
// vmtype refers to qemu (vs libvirt, krun, etc).
vmtype = machine.HyperVVirt
vmtype = define.HyperVVirt
)
const (
@ -45,40 +47,6 @@ const (
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 = `
[connection]
id=vsock0
@ -251,11 +219,11 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) {
}
m.Rootful = opts.Rootful
builder := machine.NewIgnitionBuilder(machine.DynamicIgnition{
builder := ignition.NewIgnitionBuilder(ignition.DynamicIgnition{
Name: m.RemoteUsername,
Key: key,
VMName: m.Name,
VMType: machine.HyperVVirt,
VMType: define.HyperVVirt,
TimeZone: opts.TimeZone,
WritePath: m.IgnitionFile.GetPath(),
UID: m.UID,
@ -277,28 +245,38 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) {
return false, err
}
builder.WithUnit(machine.Unit{
Enabled: machine.BoolToPtr(true),
readyUnitFile, err := createReadyUnit(m.ReadyHVSock.Port)
if err != nil {
return false, err
}
builder.WithUnit(ignition.Unit{
Enabled: ignition.BoolToPtr(true),
Name: "ready.service",
Contents: machine.StrToPtr(fmt.Sprintf(hyperVReadyUnit, m.ReadyHVSock.Port)),
Contents: ignition.StrToPtr(readyUnitFile),
})
builder.WithUnit(machine.Unit{
Contents: machine.StrToPtr(fmt.Sprintf(hyperVVsockNetUnit, m.NetworkHVSock.Port)),
Enabled: machine.BoolToPtr(true),
netUnitFile, err := createNetworkUnit(m.NetworkHVSock.Port)
if err != nil {
return false, err
}
builder.WithUnit(ignition.Unit{
Contents: ignition.StrToPtr(netUnitFile),
Enabled: ignition.BoolToPtr(true),
Name: "vsock-network.service",
})
builder.WithFile(machine.File{
Node: machine.Node{
builder.WithFile(ignition.File{
Node: ignition.Node{
Path: "/etc/NetworkManager/system-connections/vsock0.nmconnection",
},
FileEmbedded1: machine.FileEmbedded1{
FileEmbedded1: ignition.FileEmbedded1{
Append: nil,
Contents: machine.Resource{
Source: machine.EncodeDataURLPtr(hyperVVsockNMConnection),
Contents: ignition.Resource{
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
}
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 {
vmm := hypervctl.NewVirtualMachineManager()
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) {
configDir, err := machine.GetConfDir(machine.HyperVVirt)
configDir, err := machine.GetConfDir(define.HyperVVirt)
if err != nil {
return "", err
}
@ -836,7 +831,7 @@ func (m *HyperVMachine) startHostNetworking() (int32, string, machine.APIForward
}
func logCommandToFile(c *exec.Cmd, filename string) error {
dir, err := machine.GetDataDir(machine.HyperVVirt)
dir, err := machine.GetDataDir(define.HyperVVirt)
if err != nil {
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) {
dd, err := machine.GetDataDir(machine.HyperVVirt)
dd, err := machine.GetDataDir(define.HyperVVirt)
if err != nil {
return "", err
}
@ -886,7 +881,7 @@ func (m *HyperVMachine) dockerSock() (string, error) {
func (m *HyperVMachine) forwardSocketPath() (*define.VMFile, error) {
sockName := "podman.sock"
path, err := machine.GetDataDir(machine.HyperVVirt)
path, err := machine.GetDataDir(define.HyperVVirt)
if err != nil {
return nil, fmt.Errorf("Resolving data dir: %s", err.Error())
}

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
//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

View File

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

View File

@ -8,6 +8,7 @@ import (
"github.com/containers/common/pkg/config"
"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/sirupsen/logrus"
)
@ -21,14 +22,14 @@ func Get() (machine.VirtProvider, error) {
if providerOverride, found := os.LookupEnv("CONTAINERS_MACHINE_PROVIDER"); found {
provider = providerOverride
}
resolvedVMType, err := machine.ParseVMType(provider, machine.QemuVirt)
resolvedVMType, err := define.ParseVMType(provider, define.QemuVirt)
if err != nil {
return nil, err
}
logrus.Debugf("Using Podman machine with `%s` virtualization provider", resolvedVMType.String())
switch resolvedVMType {
case machine.QemuVirt:
case define.QemuVirt:
return qemu.VirtualizationProvider(), nil
default:
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/podman/v4/pkg/machine"
"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/sirupsen/logrus"
)
@ -20,16 +21,16 @@ func Get() (machine.VirtProvider, error) {
if providerOverride, found := os.LookupEnv("CONTAINERS_MACHINE_PROVIDER"); found {
provider = providerOverride
}
resolvedVMType, err := machine.ParseVMType(provider, machine.AppleHvVirt)
resolvedVMType, err := define.ParseVMType(provider, define.AppleHvVirt)
if err != nil {
return nil, err
}
logrus.Debugf("Using Podman machine with `%s` virtualization provider", resolvedVMType.String())
switch resolvedVMType {
case machine.QemuVirt:
case define.QemuVirt:
return qemu.VirtualizationProvider(), nil
case machine.AppleHvVirt:
case define.AppleHvVirt:
return applehv.VirtualizationProvider(), nil
default:
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/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/wsl"
"github.com/sirupsen/logrus"
@ -20,16 +21,16 @@ func Get() (machine.VirtProvider, error) {
if providerOverride, found := os.LookupEnv("CONTAINERS_MACHINE_PROVIDER"); found {
provider = providerOverride
}
resolvedVMType, err := machine.ParseVMType(provider, machine.WSLVirt)
resolvedVMType, err := define.ParseVMType(provider, define.WSLVirt)
if err != nil {
return nil, err
}
logrus.Debugf("Using Podman machine with `%s` virtualization provider", resolvedVMType.String())
switch resolvedVMType {
case machine.WSLVirt:
case define.WSLVirt:
return wsl.VirtualizationProvider(), nil
case machine.HyperVVirt:
case define.HyperVVirt:
return hyperv.VirtualizationProvider(), nil
default:
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
func NewGenericDownloader(vmType VMType, vmName, pullPath string) (DistributionDownload, error) {
func NewGenericDownloader(vmType define.VMType, vmName, pullPath string) (DistributionDownload, error) {
var (
imageName string
)

View File

@ -13,6 +13,7 @@ import (
"github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/compression"
"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/sockets"
"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
}
confDir, err := machine.GetConfDir(vmtype)
if err != nil {
return nil, err
}
// 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
}
@ -330,7 +336,7 @@ func (p *QEMUVirtualization) RemoveAndCleanMachines() error {
return prevErr
}
func (p *QEMUVirtualization) VMType() machine.VMType {
func (p *QEMUVirtualization) VMType() define.VMType {
return vmtype
}

View File

@ -23,6 +23,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/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/sockets"
"github.com/containers/podman/v4/pkg/machine/vmconfigs"
@ -36,7 +37,7 @@ import (
var (
// vmtype refers to qemu (vs libvirt, krun, etc).
// Could this be moved into Provider
vmtype = machine.QemuVirt
vmtype = define.QemuVirt
)
const (
@ -46,23 +47,6 @@ const (
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 {
// ConfigPath is the path to the configuration file
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")
}
builder := machine.NewIgnitionBuilder(machine.DynamicIgnition{
builder := ignition.NewIgnitionBuilder(ignition.DynamicIgnition{
Name: opts.Username,
Key: key,
VMName: v.Name,
VMType: machine.QemuVirt,
VMType: define.QemuVirt,
TimeZone: opts.TimeZone,
WritePath: v.getIgnitionFile(),
UID: v.UID,
@ -229,10 +213,14 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
return false, err
}
readyUnit := machine.Unit{
Enabled: machine.BoolToPtr(true),
readyUnitFile, err := createReadyUnitFile()
if err != nil {
return false, err
}
readyUnit := ignition.Unit{
Enabled: ignition.BoolToPtr(true),
Name: "ready.service",
Contents: machine.StrToPtr(fmt.Sprintf(qemuReadyUnit, "vport1p1", "vport1p1")),
Contents: ignition.StrToPtr(readyUnitFile),
}
builder.WithUnit(readyUnit)
@ -242,6 +230,14 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
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 {
if err := os.Remove(fmt.Sprintf("%s.pub", v.IdentityPath)); err != nil {
logrus.Error(err)
@ -1222,7 +1218,7 @@ func (v *MachineVM) isIncompatible() bool {
}
func (v *MachineVM) userGlobalSocketLink() (string, error) {
path, err := machine.GetDataDir(machine.QemuVirt)
path, err := machine.GetDataDir(define.QemuVirt)
if err != nil {
logrus.Errorf("Resolving data dir: %s", err.Error())
return "", err
@ -1233,7 +1229,7 @@ func (v *MachineVM) userGlobalSocketLink() (string, error) {
func (v *MachineVM) forwardSocketPath() (*define.VMFile, error) {
sockName := "podman.sock"
path, err := machine.GetDataDir(machine.QemuVirt)
path, err := machine.GetDataDir(define.QemuVirt)
if err != nil {
logrus.Errorf("Resolving data dir: %s", err.Error())
return nil, err

View File

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

View File

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

View File

@ -27,7 +27,7 @@ type FedoraDownload struct {
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()
if err != nil {
return nil, err

View File

@ -20,6 +20,7 @@ import (
"github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/pkg/machine/define"
"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/util"
"github.com/containers/podman/v4/utils"
@ -32,7 +33,7 @@ import (
var (
// vmtype refers to qemu (vs libvirt, krun, etc)
vmtype = machine.WSLVirt
vmtype = define.WSLVirt
)
const (
@ -717,9 +718,9 @@ func getBindMountFsTab(dist string) string {
}
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)
}