From 9d03fcc880c53385186d113fdc841ed834e63ca5 Mon Sep 17 00:00:00 2001 From: "Evgeny (\"Zhenya\") Roubinchtein" Date: Sat, 26 Mar 2022 00:52:34 -0700 Subject: [PATCH 1/3] podman machine init: add a --with-foreign-arch flag The flag is qemu-specific. It causes `qemu-static` & friends to be installed on the machine so that, e.g., x86_64 binaries can be run on aarch64 (aka "arm64"). Signed-off-by: Evgeny ("Zhenya") Roubinchtein I have done manual testing as described in the PR message, so (I believe it is the case that) [NO NEW TESTS NEEDED] --- cmd/podman/machine/init.go | 5 ++ docs/source/markdown/podman-machine-init.1.md | 7 +++ pkg/machine/config.go | 3 +- pkg/machine/ignition.go | 52 ++++++++++++++++--- pkg/machine/qemu/machine.go | 13 ++--- 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go index 518e7490fa..334bea4a1c 100644 --- a/cmd/podman/machine/init.go +++ b/cmd/podman/machine/init.go @@ -107,6 +107,11 @@ func init() { rootfulFlagName := "rootful" flags.BoolVar(&initOpts.Rootful, rootfulFlagName, false, "Whether this machine should prefer rootful container execution") + + flags.BoolVar( + &initOpts.QemuStatic, + "with-foreign-arch", false, + "Enable running binaries from \"foreign\" CPUs (e.g., run x86_64 on Apple M1 silicon).") } // TODO should we allow for a users to append to the qemu cmdline? diff --git a/docs/source/markdown/podman-machine-init.1.md b/docs/source/markdown/podman-machine-init.1.md index ac258eaaea..79df5bc8c5 100644 --- a/docs/source/markdown/podman-machine-init.1.md +++ b/docs/source/markdown/podman-machine-init.1.md @@ -87,6 +87,13 @@ so mounts must be created under the /mnt directory. Driver to use for mounting volumes from the host, such as `virtfs`. +#### **--with-foreign-arch** + +Enable running binaries compiled for "foreign" CPUs (e.g., run x86_64 binaries on +Apple M1 silicon). This option only works for Qemu machines. It works by installing +qemu-static and qemu-binfmt packages on the machine. The initialization process will +likely take longer if this option is enabled. + ## EXAMPLES ``` diff --git a/pkg/machine/config.go b/pkg/machine/config.go index 7e1561506e..959b0bbf21 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -30,7 +30,8 @@ type InitOptions struct { ReExec bool Rootful bool // The numerical userid of the user that called machine - UID string + UID string + QemuStatic bool } type QemuMachineStatus = string diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go index fe47437e3b..949a0bdd35 100644 --- a/pkg/machine/ignition.go +++ b/pkg/machine/ignition.go @@ -11,6 +11,7 @@ import ( "net/url" "os" "path/filepath" + "regexp" "github.com/containers/common/pkg/config" "github.com/sirupsen/logrus" @@ -49,12 +50,13 @@ func getNodeGrp(grpName string) NodeGroup { } type DynamicIgnition struct { - Name string - Key string - TimeZone string - UID int - VMName string - WritePath string + Name string + Key string + TimeZone string + UID int + VMName string + WritePath string + QemuStatic bool } // NewIgnitionFile @@ -184,6 +186,39 @@ ExecStartPost=/usr/bin/systemctl daemon-reload [Install] WantedBy=sysinit.target ` + qemuStatic := `[Unit] +Description=Layer qemu-user-static & Co with rpm-ostree +Wants=network-online.target +After=network-online.target +After=remove-moby.service +# We run before 'zincati.service' to avoid conflicting with rpm-ostree +# transactions. +Before=zincati.service +ConditionPathIsDirectory=|!/lib/binfmt.d +ConditionDirectoryNotEmpty=|!/lib/binfmt.d + +[Service] +Type=oneshot +RemainAfterExit=yes +# '--allow-inactive' ensures that rpm-ostree does not return an error +# if the package is already installed. This is useful if the package is +# added to the root image in a future Fedora CoreOS release as it will +# prevent the service from failing. +ExecStart=/usr/bin/rpm-ostree install --apply-live --allow-inactive qemu qemu-user-static qemu-user-binfmt +# The 'systetmd-binfmt.service' unit _will_ do this, but it has long completed by the time this service is starting +# So just run the command to enable the extra formats right away. +ExecStart=/usr/lib/systemd/systemd-binfmt + +[Install] +WantedBy=multi-user.target +` + + if ign.QemuStatic { + pat := regexp.MustCompile(`(?m)^(After=.*sshd\.service)$`) + r := pat.ReplaceAllString(ready, `$1 install-qemu-static.service`) + ready = r + } + _ = ready ignSystemd := Systemd{ Units: []Unit{ @@ -216,6 +251,11 @@ WantedBy=sysinit.target Name: "envset-fwcfg.service", Contents: &envset, }, + { + Enabled: &ign.QemuStatic, + Name: "install-qemu-static.service", + Contents: &qemuStatic, + }, }} ignConfig := Config{ Ignition: ignVersion, diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 07155bbcff..0794ea8bd8 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -408,12 +408,13 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { } // Write the ignition file ign := machine.DynamicIgnition{ - Name: opts.Username, - Key: key, - VMName: v.Name, - TimeZone: opts.TimeZone, - WritePath: v.IgnitionFilePath, - UID: v.UID, + Name: opts.Username, + Key: key, + VMName: v.Name, + TimeZone: opts.TimeZone, + WritePath: v.IgnitionFilePath, + UID: v.UID, + QemuStatic: opts.QemuStatic, } err = machine.NewIgnitionFile(ign) return err == nil, err From 2ad561dcf1afdff144566482708e1a4ef2501584 Mon Sep 17 00:00:00 2001 From: "Evgeny (\"Zhenya\") Roubinchtein" Date: Tue, 29 Mar 2022 08:53:50 -0700 Subject: [PATCH 2/3] fixup! podman machine init: add a --with-foreign-arch flag Explain what manipulation of the text of the `ready` unit intends to accomplish. Signed-off-by: Evgeny ("Zhenya") Roubinchtein --- pkg/machine/ignition.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go index 949a0bdd35..9fd9a6fc6a 100644 --- a/pkg/machine/ignition.go +++ b/pkg/machine/ignition.go @@ -214,6 +214,7 @@ WantedBy=multi-user.target ` if ign.QemuStatic { + // Make the `ready` service wait until `install-qemu-static` has run to completion. pat := regexp.MustCompile(`(?m)^(After=.*sshd\.service)$`) r := pat.ReplaceAllString(ready, `$1 install-qemu-static.service`) ready = r From e9a71ad09021a1fea6e4f5bbea5c025c3b0befe3 Mon Sep 17 00:00:00 2001 From: "Evgeny (\"Zhenya\") Roubinchtein" Date: Tue, 29 Mar 2022 09:01:21 -0700 Subject: [PATCH 3/3] fixup! podman machine init: add a --with-foreign-arch flag Use the `/var/lib/.stamp` convention for the `install-qemu-static` unit. Signed-off-by: Evgeny ("Zhenya") Roubinchtein --- pkg/machine/ignition.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go index 9fd9a6fc6a..1415c51d51 100644 --- a/pkg/machine/ignition.go +++ b/pkg/machine/ignition.go @@ -194,8 +194,7 @@ After=remove-moby.service # We run before 'zincati.service' to avoid conflicting with rpm-ostree # transactions. Before=zincati.service -ConditionPathIsDirectory=|!/lib/binfmt.d -ConditionDirectoryNotEmpty=|!/lib/binfmt.d +ConditionPathExists=!/var/lib/%N.stamp [Service] Type=oneshot @@ -208,6 +207,7 @@ ExecStart=/usr/bin/rpm-ostree install --apply-live --allow-inactive qemu qemu-us # The 'systetmd-binfmt.service' unit _will_ do this, but it has long completed by the time this service is starting # So just run the command to enable the extra formats right away. ExecStart=/usr/lib/systemd/systemd-binfmt +ExecStartPost=/bin/touch /var/lib/%N.stamp [Install] WantedBy=multi-user.target