Merge pull request #25945 from ninja-quokka/podman_machine_swap

feat: Add support for configuring swap in Podman machine
This commit is contained in:
openshift-merge-bot[bot]
2025-05-02 13:21:48 +00:00
committed by GitHub
13 changed files with 81 additions and 17 deletions

View File

@ -83,6 +83,14 @@ func init() {
)
_ = initCmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone)
swapFlagName := "swap"
flags.Uint64VarP(
&initOpts.Swap,
swapFlagName, "s", 0,
"Swap in MiB",
)
_ = initCmd.RegisterFlagCompletionFunc(swapFlagName, completion.AutocompleteNone)
flags.BoolVar(
&now,
"now", false,

View File

@ -119,6 +119,7 @@ func outputTemplate(cmd *cobra.Command, responses []*entities.ListReporter) erro
"CPUs": "CPUS",
"Memory": "MEMORY",
"DiskSize": "DISK SIZE",
"Swap": "SWAP",
})
rpt := report.New(os.Stdout, cmd.Name())
@ -182,6 +183,7 @@ func toMachineFormat(vms []*machine.ListResponse, defaultCon *config.Connection)
response.VMType = vm.VMType
response.CPUs = vm.CPUs
response.Memory = strUint(uint64(vm.Memory.ToBytes()))
response.Swap = strUint(uint64(vm.Swap.ToBytes()))
response.DiskSize = strUint(uint64(vm.DiskSize.ToBytes()))
response.Port = vm.Port
response.RemoteUsername = vm.RemoteUsername
@ -225,6 +227,7 @@ func toHumanFormat(vms []*machine.ListResponse, defaultCon *config.Connection) [
response.VMType = vm.VMType
response.CPUs = vm.CPUs
response.Memory = units.BytesSize(float64(vm.Memory.ToBytes()))
response.Swap = units.BytesSize(float64(vm.Swap.ToBytes()))
response.DiskSize = units.BytesSize(float64(vm.DiskSize.ToBytes()))
humanResponses = append(humanResponses, response)

View File

@ -104,6 +104,12 @@ if there is no existing remote connection configurations.
API forwarding, if available, follows this setting.
#### **--swap**, **-s**=*number*
Swap (in MiB). Note: 1024MiB = 1GiB.
Renders a `zram-generator.conf` file with zram-size set to the value passed to --swap
#### **--timezone**
Set the timezone for the machine and containers. Valid values are `local` or

View File

@ -50,6 +50,7 @@ Valid placeholders for the Go template are listed below:
| .RemoteUsername | VM Username for rootless Podman |
| .Running | Is machine running |
| .Stream | Stream name |
| .Swap | Allocated swap for machine |
| .UserModeNetworking | Whether machine uses user-mode networking |
| .VMType | VM type |

View File

@ -13,6 +13,7 @@ type ListReporter struct {
VMType string
CPUs uint64
Memory string
Swap string
DiskSize string
Port int
RemoteUsername string

View File

@ -22,9 +22,7 @@ import (
const apiUpTimeout = 20 * time.Second
var (
ForwarderBinaryName = "gvproxy"
)
var ForwarderBinaryName = "gvproxy"
type Download struct {
Arch string
@ -55,6 +53,7 @@ type ListResponse struct {
VMType string
CPUs uint64
Memory strongunits.MiB
Swap strongunits.MiB
DiskSize strongunits.GiB
Port int
RemoteUsername string

View File

@ -11,6 +11,7 @@ type InitOptions struct {
Volumes []string
IsDefault bool
Memory uint64
Swap uint64
Name string
TimeZone string
URI url.URL

View File

@ -28,6 +28,7 @@ type initMachine struct {
playbook string
cpus *uint
diskSize *uint
swap *uint
ignitionPath string
username string
image string
@ -81,6 +82,9 @@ func (i *initMachine) buildCmd(m *machineTestBuilder) []string {
if i.userModeNetworking {
cmd = append(cmd, "--user-mode-networking")
}
if i.swap != nil {
cmd = append(cmd, "--swap", strconv.Itoa(int(*i.swap)))
}
name := m.name
cmd = append(cmd, name)
@ -112,11 +116,17 @@ func (i *initMachine) withCPUs(num uint) *initMachine {
i.cpus = &num
return i
}
func (i *initMachine) withDiskSize(size uint) *initMachine {
i.diskSize = &size
return i
}
func (i *initMachine) withSwap(size uint) *initMachine {
i.swap = &size
return i
}
func (i *initMachine) withIgnitionPath(path string) *initMachine {
i.ignitionPath = path
return i

View File

@ -238,7 +238,6 @@ var _ = Describe("podman machine init", func() {
Expect(testMachine.Resources.Memory).To(BeEquivalentTo(uint64(2048)))
}
Expect(testMachine.SSHConfig.RemoteUsername).To(Equal(remoteUsername))
})
It("machine init with cpus, disk size, memory, timezone", func() {
@ -282,6 +281,23 @@ var _ = Describe("podman machine init", func() {
Expect(timezoneSession.outputToString()).To(ContainSubstring("HST"))
})
It("machine init with swap", func() {
skipIfWSL("Configuring swap is not supported on WSL")
name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImage(mb.imagePath).withSwap(2048).withNow()).run()
Expect(err).ToNot(HaveOccurred())
Expect(session).To(Exit(0))
ssh := &sshMachine{}
sshSession, err := mb.setName(name).setCmd(ssh.withSSHCommand([]string{"zramctl -bo DISKSIZE"})).run()
Expect(err).ToNot(HaveOccurred())
Expect(sshSession).To(Exit(0))
// 2147483648 bytes = 2048MiB
Expect(sshSession.outputToString()).To(ContainSubstring("2147483648"))
})
It("machine init with volume", func() {
if testProvider.VMType() == define.HyperVVirt {
Skip("volumes are not supported on hyperv yet")
@ -373,7 +389,6 @@ var _ = Describe("podman machine init", func() {
output := strings.TrimSpace(sshSession2.outputToString())
Expect(output).To(HavePrefix("/run/user"))
Expect(output).To(HaveSuffix("/podman/podman.sock"))
})
It("machine init rootful with docker.sock check", func() {

View File

@ -67,6 +67,7 @@ type DynamicIgnition struct {
Rootful bool
NetRecover bool
Rosetta bool
Swap uint64
}
func (ign *DynamicIgnition) Write() error {
@ -136,7 +137,7 @@ func (ign *DynamicIgnition) GenerateIgnitionConfig() error {
ignStorage := Storage{
Directories: getDirs(ign.Name),
Files: getFiles(ign.Name, ign.UID, ign.Rootful, ign.VMType, ign.NetRecover),
Files: getFiles(ign.Name, ign.UID, ign.Rootful, ign.VMType, ign.NetRecover, ign.Swap),
Links: getLinks(ign.Name),
}
@ -293,7 +294,7 @@ func getDirs(usrName string) []Directory {
return dirs
}
func getFiles(usrName string, uid int, rootful bool, vmtype define.VMType, _ bool) []File {
func getFiles(usrName string, uid int, rootful bool, vmtype define.VMType, _ bool, swap uint64) []File {
files := make([]File, 0)
lingerExample := parser.NewUnitFile()
@ -407,6 +408,21 @@ pids_limit=0
},
})
if swap > 0 {
files = append(files, File{
Node: Node{
Path: "/etc/systemd/zram-generator.conf",
},
FileEmbedded1: FileEmbedded1{
Append: nil,
Contents: Resource{
Source: EncodeDataURLPtr(fmt.Sprintf("[zram0]\nzram-size=%d\n", swap)),
},
Mode: IntToPtr(0644),
},
})
}
// get certs for current user
userHome, err := os.UserHomeDir()
if err != nil {

View File

@ -32,9 +32,7 @@ import (
// List is done at the host level to allow for a *possible* future where
// more than one provider is used
func List(vmstubbers []vmconfigs.VMProvider, _ machine.ListOptions) ([]*machine.ListResponse, error) {
var (
lrs []*machine.ListResponse
)
var lrs []*machine.ListResponse
for _, s := range vmstubbers {
dirs, err := env.GetMachineDirs(s.VMType())
@ -51,15 +49,15 @@ func List(vmstubbers []vmconfigs.VMProvider, _ machine.ListOptions) ([]*machine.
return nil, err
}
lr := machine.ListResponse{
Name: name,
CreatedAt: mc.Created,
LastUp: mc.LastUp,
Running: state == machineDefine.Running,
Starting: mc.Starting,
//Stream: "", // No longer applicable
Name: name,
CreatedAt: mc.Created,
LastUp: mc.LastUp,
Running: state == machineDefine.Running,
Starting: mc.Starting,
VMType: s.VMType().String(),
CPUs: mc.Resources.CPUs,
Memory: mc.Resources.Memory,
Swap: mc.Swap,
DiskSize: mc.Resources.DiskSize,
Port: mc.SSH.Port,
RemoteUsername: mc.SSH.RemoteUsername,
@ -206,13 +204,13 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) error {
VMType: mp.VMType(),
WritePath: ignitionFile.GetPath(),
Rootful: opts.Rootful,
Swap: opts.Swap,
})
// If the user provides an ignition file, we need to
// copy it into the conf dir
if len(opts.IgnitionPath) > 0 {
err = ignBuilder.BuildWithIgnitionFile(opts.IgnitionPath)
if err != nil {
return err
}

View File

@ -27,6 +27,8 @@ type MachineConfig struct {
SSH SSHConfig
Version uint
Swap strongunits.MiB
// Image stuff
imageDescription machineImage //nolint:unused

View File

@ -81,6 +81,10 @@ func NewMachineConfig(opts define.InitOptions, dirs *define.MachineDirs, sshIden
}
mc.Resources = mrc
if opts.Swap > 0 {
mc.Swap = strongunits.MiB(opts.Swap)
}
sshPort, err := ports.AllocateMachinePort()
if err != nil {
return nil, err