summaryrefslogtreecommitdiff
path: root/pkg/machine
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/machine')
-rw-r--r--pkg/machine/config.go3
-rw-r--r--pkg/machine/ignition.go28
-rw-r--r--pkg/machine/qemu/config.go7
-rw-r--r--pkg/machine/qemu/machine.go49
-rw-r--r--pkg/machine/qemu/options_darwin_arm64.go1
5 files changed, 76 insertions, 12 deletions
diff --git a/pkg/machine/config.go b/pkg/machine/config.go
index efb1eda15..b3b105150 100644
--- a/pkg/machine/config.go
+++ b/pkg/machine/config.go
@@ -1,3 +1,4 @@
+//go:build amd64 || arm64
// +build amd64 arm64
package machine
@@ -28,6 +29,8 @@ type InitOptions struct {
Username string
ReExec bool
Rootful bool
+ // The numberical userid of the user that called machine
+ UID string
}
type QemuMachineStatus = string
diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go
index 47b1836f0..b2dabb689 100644
--- a/pkg/machine/ignition.go
+++ b/pkg/machine/ignition.go
@@ -51,6 +51,7 @@ type DynamicIgnition struct {
Name string
Key string
TimeZone string
+ UID int
VMName string
WritePath string
}
@@ -63,12 +64,13 @@ func NewIgnitionFile(ign DynamicIgnition) error {
ignVersion := Ignition{
Version: "3.2.0",
}
-
ignPassword := Passwd{
Users: []PasswdUser{
{
Name: ign.Name,
SSHAuthorizedKeys: []SSHAuthorizedKey{SSHAuthorizedKey(ign.Key)},
+ // Set the UID of the core user inside the machine
+ UID: intToPtr(ign.UID),
},
{
Name: "root",
@@ -289,9 +291,7 @@ func getDirs(usrName string) []Directory {
}
func getFiles(usrName string) []File {
- var (
- files []File
- )
+ files := make([]File, 0)
lingerExample := `[Unit]
Description=A systemd user unit demo
@@ -310,6 +310,7 @@ machine_enabled=true
delegateConf := `[Service]
Delegate=memory pids cpu io
`
+ subUID := `%s:100000:1000000`
// Add a fake systemd service to get the user socket rolling
files = append(files, File{
@@ -344,6 +345,25 @@ Delegate=memory pids cpu io
},
})
+ // Setup /etc/subuid and /etc/subgid
+ for _, sub := range []string{"/etc/subuid", "/etc/subgid"} {
+ files = append(files, File{
+ Node: Node{
+ Group: getNodeGrp("root"),
+ Path: sub,
+ User: getNodeUsr("root"),
+ Overwrite: boolToPtr(true),
+ },
+ FileEmbedded1: FileEmbedded1{
+ Append: nil,
+ Contents: Resource{
+ Source: encodeDataURLPtr(fmt.Sprintf(subUID, usrName)),
+ },
+ Mode: intToPtr(0744),
+ },
+ })
+ }
+
// Set delegate.conf so cpu,io subsystem is delegated to non-root users as well for cgroupv2
// by default
files = append(files, File{
diff --git a/pkg/machine/qemu/config.go b/pkg/machine/qemu/config.go
index c619b7dd4..b39334be0 100644
--- a/pkg/machine/qemu/config.go
+++ b/pkg/machine/qemu/config.go
@@ -1,8 +1,11 @@
+//go:build (amd64 && !windows) || (arm64 && !windows)
// +build amd64,!windows arm64,!windows
package qemu
-import "time"
+import (
+ "time"
+)
type Provider struct{}
@@ -35,6 +38,8 @@ type MachineVM struct {
RemoteUsername string
// Whether this machine should run in a rootful or rootless manner
Rootful bool
+ // UID is the numerical id of the user that called machine
+ UID int
}
type Mount struct {
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index 8b567fb26..43a79dae8 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -88,11 +88,16 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) {
vm.Memory = opts.Memory
vm.DiskSize = opts.DiskSize
- // Look up the executable
- execPath, err := exec.LookPath(QemuCommand)
+ // Find the qemu executable
+ cfg, err := config.Default()
if err != nil {
return nil, err
}
+ execPath, err := cfg.FindHelperBinary(QemuCommand, true)
+ if err != nil {
+ return nil, err
+ }
+
cmd := append([]string{execPath})
// Add memory
cmd = append(cmd, []string{"-m", strconv.Itoa(int(vm.Memory))}...)
@@ -245,12 +250,13 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
}
}
v.Mounts = mounts
+ v.UID = os.Getuid()
// Add location of bootable image
v.CmdLine = append(v.CmdLine, "-drive", "if=virtio,file="+v.ImagePath)
// This kind of stinks but no other way around this r/n
if len(opts.IgnitionPath) < 1 {
- uri := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/user/1000/podman/podman.sock", strconv.Itoa(v.Port), v.RemoteUsername)
+ uri := machine.SSHRemoteConnection.MakeSSHURL("localhost", fmt.Sprintf("/run/user/%d/podman/podman.sock", v.UID), strconv.Itoa(v.Port), v.RemoteUsername)
uriRoot := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/podman/podman.sock", strconv.Itoa(v.Port), "root")
identity := filepath.Join(sshDir, v.Name)
@@ -296,7 +302,16 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
// only if the virtualdisk size is less than
// the given disk size
if opts.DiskSize<<(10*3) > originalDiskSize {
- resize := exec.Command("qemu-img", []string{"resize", v.ImagePath, strconv.Itoa(int(opts.DiskSize)) + "G"}...)
+ // Find the qemu executable
+ cfg, err := config.Default()
+ if err != nil {
+ return false, err
+ }
+ resizePath, err := cfg.FindHelperBinary("qemu-img", true)
+ if err != nil {
+ return false, err
+ }
+ resize := exec.Command(resizePath, []string{"resize", v.ImagePath, strconv.Itoa(int(opts.DiskSize)) + "G"}...)
resize.Stdout = os.Stdout
resize.Stderr = os.Stderr
if err := resize.Run(); err != nil {
@@ -319,6 +334,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
VMName: v.Name,
TimeZone: opts.TimeZone,
WritePath: v.IgnitionFilePath,
+ UID: v.UID,
}
err = machine.NewIgnitionFile(ign)
return err == nil, err
@@ -459,7 +475,17 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
for _, mount := range v.Mounts {
fmt.Printf("Mounting volume... %s:%s\n", mount.Source, mount.Target)
// create mountpoint directory if it doesn't exist
- err = v.SSH(name, machine.SSHOptions{Args: []string{"-q", "--", "sudo", "mkdir", "-p", mount.Target}})
+ // because / is immutable, we have to monkey around with permissions
+ // if we dont mount in /home or /mnt
+ args := []string{"-q", "--"}
+ if !strings.HasPrefix(mount.Target, "/home") || !strings.HasPrefix(mount.Target, "/mnt") {
+ args = append(args, "sudo", "chattr", "-i", "/", ";")
+ }
+ args = append(args, "sudo", "mkdir", "-p", mount.Target)
+ if !strings.HasPrefix(mount.Target, "/home") || !strings.HasPrefix(mount.Target, "/mnt") {
+ args = append(args, ";", "sudo", "chattr", "+i", "/", ";")
+ }
+ err = v.SSH(name, machine.SSHOptions{Args: args})
if err != nil {
return err
}
@@ -795,7 +821,16 @@ func (v *MachineVM) SSH(name string, opts machine.SSHOptions) error {
// executes qemu-image info to get the virtual disk size
// of the diskimage
func getDiskSize(path string) (uint64, error) {
- diskInfo := exec.Command("qemu-img", "info", "--output", "json", path)
+ // Find the qemu executable
+ cfg, err := config.Default()
+ if err != nil {
+ return 0, err
+ }
+ qemuPathDir, err := cfg.FindHelperBinary("qemu-img", true)
+ if err != nil {
+ return 0, err
+ }
+ diskInfo := exec.Command(qemuPathDir, "info", "--output", "json", path)
stdout, err := diskInfo.StdoutPipe()
if err != nil {
return 0, err
@@ -957,7 +992,7 @@ func (v *MachineVM) setupAPIForwarding(cmd []string) ([]string, string, apiForwa
return cmd, "", noForwarding
}
- destSock := "/run/user/1000/podman/podman.sock"
+ destSock := fmt.Sprintf("/run/user/%d/podman/podman.sock", v.UID)
forwardUser := "core"
if v.Rootful {
diff --git a/pkg/machine/qemu/options_darwin_arm64.go b/pkg/machine/qemu/options_darwin_arm64.go
index 727a275d2..5b6cdc86d 100644
--- a/pkg/machine/qemu/options_darwin_arm64.go
+++ b/pkg/machine/qemu/options_darwin_arm64.go
@@ -45,6 +45,7 @@ func getOvmfDir(imagePath, vmName string) string {
*/
func getEdk2CodeFd(name string) string {
dirs := []string{
+ "/opt/homebrew/opt/podman/libexec/share/qemu",
"/usr/local/share/qemu",
"/opt/homebrew/share/qemu",
}