til: docker_emulate-s390x-with-qemu.md
This data as json
| path | topic | title | url | body | html | shot | created | created_utc | updated | updated_utc | shot_hash | slug |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| docker_emulate-s390x-with-qemu.md | docker | Emulating a big-endian s390x with QEMU | https://github.com/simonw/til/blob/main/docker/emulate-s390x-with-qemu.md | I got [a bug report](https://github.com/simonw/sqlite-fts4/issues/6) concerning my [sqlite-fts4](https://github.com/simonw/sqlite-fts4) project running on PPC64 and s390x architectures. The s390x is an [IBM mainframe architecture](https://en.wikipedia.org/wiki/Linux_on_IBM_Z), which I found glamorous! The bug related to those machines being big-endian v.s. my software being tested on little-endian machines. My first attempt at fixing it (see [this TIL](https://til.simonwillison.net/python/struct-endianness)) turned out not to be correct. I really needed a way to test agaist an emulated s390x machine with big-endian byte order. I figured out how to do that using Docker for Mac and QEMU. ## multiarch/qemu-user-static:register This is the first command to run. It does something magical to your Docker installation: docker run --rm --privileged multiarch/qemu-user-static:register --reset The [qemu-user-static README](https://github.com/multiarch/qemu-user-static/blob/master/README.md) says: > `multiarch/qemu-user-static` and `multiarch/qemu-user-static:register` images execute the register script that registers below kind of `/proc/sys/fs/binfmt_misc/qemu-$arch` files for all supported processors except the current one in it when running the container. It continues: > The `--reset` option is implemented at the register script that executes find `/proc/sys/fs/binfmt_misc -type f -name 'qemu-*' -exec sh -c 'echo -1 > {}' \;` to remove `binfmt_misc` entry files before register the entry. I don't understand what this means. But running this command was essential for the next command to work. ## multiarch/ubuntu-core:s390x-focal Having run that command, the following command drops you into a shell in an emulated s390x machine running Ubuntu Focal: docker run -it multiarch/ubuntu-core:s390x-focal /bin/bash Using `-focal` gives you Python 3.8. I previously tried `s390x-bionic` but that gave me Python 3.6. You don't actually get Python until you install it, like so: apt-get -y update && apt-get -y install python3 This will take a while. I think it's slower because the hardware is being emulated. Now you can check the Python version and confirm that the byte order is big-endian like this: ``` root@ea63e288ce49:/# python3 --version Python 3.8.10 root@ea63e288ce49:/# python3 -c 'import sys; print(sys.byteorder)' big ``` ## Doing this in GitHub Actions I figured out the [following recipe](https://github.com/simonw/playing-with-actions-2/blob/4408f8136b8b37160685e8961742eb11589b3f66/.github/workflows/qemu.yml) for running this in GitHub Actions. In this example I'm cloning my `sqlite-fts4` repo and running the tests in it as well: ```yaml name: QEMU to run s390x-focal on: push: workflow_dispatch: jobs: one: runs-on: ubuntu-latest steps: - name: Setup multiarch/qemu-user-static run: | docker run --rm --privileged multiarch/qemu-user-static:register --reset - name: ubuntu-core:s390x-focal uses: docker://multiarch/ubuntu-core:s390x-focal with: args: > bash -c "uname -a && lscpu | grep Endian && apt-get -y update && apt-get -y install python3 git python3.8-venv && python3 --version && python3 -c 'import sys; print(sys.byteorder)' && git clone https://github.com/simonw/sqlite-fts4 && cd sqlite-fts4 && python3 -m venv venv && source venv/bin/activate && pip install -e '.[test]' && pytest " ``` | <p>I got <a href="https://github.com/simonw/sqlite-fts4/issues/6">a bug report</a> concerning my <a href="https://github.com/simonw/sqlite-fts4">sqlite-fts4</a> project running on PPC64 and s390x architectures.</p> <p>The s390x is an <a href="https://en.wikipedia.org/wiki/Linux_on_IBM_Z" rel="nofollow">IBM mainframe architecture</a>, which I found glamorous!</p> <p>The bug related to those machines being big-endian v.s. my software being tested on little-endian machines. My first attempt at fixing it (see <a href="https://til.simonwillison.net/python/struct-endianness" rel="nofollow">this TIL</a>) turned out not to be correct. I really needed a way to test agaist an emulated s390x machine with big-endian byte order.</p> <p>I figured out how to do that using Docker for Mac and QEMU.</p> <h2> <a id="user-content-multiarchqemu-user-staticregister" class="anchor" href="#multiarchqemu-user-staticregister" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>multiarch/qemu-user-static:register</h2> <p>This is the first command to run. It does something magical to your Docker installation:</p> <pre><code>docker run --rm --privileged multiarch/qemu-user-static:register --reset </code></pre> <p>The <a href="https://github.com/multiarch/qemu-user-static/blob/master/README.md">qemu-user-static README</a> says:</p> <blockquote> <p><code>multiarch/qemu-user-static</code> and <code>multiarch/qemu-user-static:register</code> images execute the register script that registers below kind of <code>/proc/sys/fs/binfmt_misc/qemu-$arch</code> files for all supported processors except the current one in it when running the container.</p> </blockquote> <p>It continues:</p> <blockquote> <p>The <code>--reset</code> option is implemented at the register script that executes find <code>/proc/sys/fs/binfmt_misc -type f -name 'qemu-*' -exec sh -c 'echo -1 > {}' \;</code> to remove <code>binfmt_misc</code> entry files before register the entry.</p> </blockquote> <p>I don't understand what this means. But running this command was essential for the next command to work.</p> <h2> <a id="user-content-multiarchubuntu-cores390x-focal" class="anchor" href="#multiarchubuntu-cores390x-focal" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>multiarch/ubuntu-core:s390x-focal</h2> <p>Having run that command, the following command drops you into a shell in an emulated s390x machine running Ubuntu Focal:</p> <pre><code>docker run -it multiarch/ubuntu-core:s390x-focal /bin/bash </code></pre> <p>Using <code>-focal</code> gives you Python 3.8. I previously tried <code>s390x-bionic</code> but that gave me Python 3.6.</p> <p>You don't actually get Python until you install it, like so:</p> <pre><code>apt-get -y update && apt-get -y install python3 </code></pre> <p>This will take a while. I think it's slower because the hardware is being emulated.</p> <p>Now you can check the Python version and confirm that the byte order is big-endian like this:</p> <pre><code>root@ea63e288ce49:/# python3 --version Python 3.8.10 root@ea63e288ce49:/# python3 -c 'import sys; print(sys.byteorder)' big </code></pre> <h2> <a id="user-content-doing-this-in-github-actions" class="anchor" href="#doing-this-in-github-actions" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Doing this in GitHub Actions</h2> <p>I figured out the <a href="https://github.com/simonw/playing-with-actions-2/blob/4408f8136b8b37160685e8961742eb11589b3f66/.github/workflows/qemu.yml">following recipe</a> for running this in GitHub Actions.</p> <p>In this example I'm cloning my <code>sqlite-fts4</code> repo and running the tests in it as well:</p> <div class="highlight highlight-source-yaml"><pre><span class="pl-ent">name</span>: <span class="pl-s">QEMU to run s390x-focal</span> <span class="pl-ent">on</span>: <span class="pl-ent">push</span>: <span class="pl-ent">workflow_dispatch</span>: <span class="pl-ent">jobs</span>: <span class="pl-ent">one</span>: <span class="pl-ent">runs-on</span>: <span class="pl-s">ubuntu-latest</span> <span class="pl-ent">steps</span>: - <span class="pl-ent">name</span>: <span class="pl-s">Setup multiarch/qemu-user-static</span> <span class="pl-ent">run</span>: <span class="pl-s">|</span> <span class="pl-s"> docker run --rm --privileged multiarch/qemu-user-static:register --reset</span> <span class="pl-s"></span> - <span class="pl-ent">name</span>: <span class="pl-s">ubuntu-core:s390x-focal</span> <span class="pl-ent">uses</span>: <span class="pl-s">docker://multiarch/ubuntu-core:s390x-focal</span> <span class="pl-ent">with</span>: <span class="pl-ent">args</span>: <span class="pl-s">></span> <span class="pl-s"> bash -c</span> <span class="pl-s"> "uname -a &&</span> <span class="pl-s"> lscpu | grep Endian &&</span> <span class="pl-s"> apt-get -y update &&</span> <span class="pl-s"> apt-get -y install python3 git python3.8-venv &&</span> <span class="pl-s"> python3 --version &&</span> <span class="pl-s"> python3 -c 'import sys; print(sys.byteorder)' &&</span> <span class="pl-s"> git clone https://github.com/simonw/sqlite-fts4 &&</span> <span class="pl-s"> cd sqlite-fts4 &&</span> <span class="pl-s"> python3 -m venv venv &&</span> <span class="pl-s"> source venv/bin/activate &&</span> <span class="pl-s"> pip install -e '.[test]' &&</span> <span class="pl-s"> pytest</span> <span class="pl-s"> "</span></pre></div> | <Binary: 75,331 bytes> | 2022-07-29T19:44:50-07:00 | 2022-07-30T02:44:50+00:00 | 2022-07-29T19:44:50-07:00 | 2022-07-30T02:44:50+00:00 | 6069203118a27e680e662ef1f051a50c | emulate-s390x-with-qemu |