diff options
| author | Bruce Ashfield <bruce.ashfield@gmail.com> | 2026-02-12 18:31:00 +0000 |
|---|---|---|
| committer | Bruce Ashfield <bruce.ashfield@gmail.com> | 2026-02-26 01:05:01 +0000 |
| commit | 0fe8c4444f3199b862a4ba52b2b62b5f9b2af85f (patch) | |
| tree | 3ed29a52302003a532f674b20dd3466f4eae8da0 /recipes-extended | |
| parent | 2f3dcd4e0a45d1b976d266f04912fe43c68586f5 (diff) | |
| download | meta-virtualization-0fe8c4444f3199b862a4ba52b2b62b5f9b2af85f.tar.gz | |
xen: document guest import system and add tests
Add 3rd-party guest import section to README-xen.md covering
import types, kernel modes, Alpine example, and how to add
custom import handlers.
Add test_xen_guest_bundle.py with 46 pytest tests covering
bbclass structure, import handlers, kernel modes, license
warning, Alpine recipe, and README content.
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'recipes-extended')
| -rw-r--r-- | recipes-extended/images/README-xen.md | 224 |
1 files changed, 129 insertions, 95 deletions
diff --git a/recipes-extended/images/README-xen.md b/recipes-extended/images/README-xen.md index 82d72364..f16aa743 100644 --- a/recipes-extended/images/README-xen.md +++ b/recipes-extended/images/README-xen.md | |||
| @@ -20,154 +20,188 @@ to differentiate). | |||
| 20 | 20 | ||
| 21 | It creates tarballs, ext4 and qcow images for testing purposes. | 21 | It creates tarballs, ext4 and qcow images for testing purposes. |
| 22 | 22 | ||
| 23 | bundling | 23 | Bundling |
| 24 | -------- | 24 | -------- |
| 25 | 25 | ||
| 26 | Guests can be bundled automatically through the following mechanisms: | 26 | There are two ways to bundle Xen guests into a Dom0 host image: |
| 27 | 27 | ||
| 28 | - via the variable XEN_BUNDLED_GUESTS | 28 | | Use Case | `BUNDLED_XEN_GUESTS` | Bundle Recipe | |
| 29 | - via a xen configuration file in the deploy directory of the format | 29 | |---|---|---| |
| 30 | xen-guest-bundle-*.cfg | 30 | | Simple: guests in one host image | recommended | overkill | |
| 31 | | Reuse guests across multiple host images | repetitive | recommended | | ||
| 32 | | Package versioning and dependencies | not supported | supported | | ||
| 33 | | Distribute pre-built guest sets | not supported | supported | | ||
| 31 | 34 | ||
| 32 | The guests can be built via OE, or be 3rd party guests. They just | 35 | ### Variable-driven (BUNDLED_XEN_GUESTS) |
| 33 | must be in the deploy directory so they can be copied into the rootfs | ||
| 34 | of the xen host image | ||
| 35 | 36 | ||
| 36 | Type 1) XEN_BUNDLED_GUESTS | 37 | Guests can be bundled into the host image automatically using |
| 38 | `xen-guest-cross-install.bbclass` (inherited by xen-image-minimal). | ||
| 37 | 39 | ||
| 38 | If XEN_BUNDLED_GUESTS is used, it is simply a colon separated list of | 40 | Set `BUNDLED_XEN_GUESTS` in local.conf or the image recipe: |
| 39 | rootfs:kernels. Normal variable rules apply, so it can be set in a | ||
| 40 | local.conf, or in a bbappend to the image recipe. | ||
| 41 | 41 | ||
| 42 | An example would be: | 42 | BUNDLED_XEN_GUESTS = "xen-guest-image-minimal:autostart" |
| 43 | 43 | ||
| 44 | XEN_BUNDLED_GUESTS = "xen-guest-image-minimal-qemuarm64.rootfs.ext4:Image" | 44 | Each entry is a recipe name with optional tags: |
| 45 | 45 | ||
| 46 | These point at symlinks created in the image deploy directory, or they | 46 | recipe-name[:autostart][:external] |
| 47 | can be specific images/kernels without the symlink. | ||
| 48 | 47 | ||
| 49 | Type 2) A Xen guest configuration file | 48 | - recipe-name: Yocto image recipe that produces the guest rootfs |
| 49 | - autostart: Creates symlink in /etc/xen/auto/ for xendomains | ||
| 50 | - external: Skip dependency generation (3rd-party guest) | ||
| 50 | 51 | ||
| 51 | If xen guest configuration files are found in the deploy directories | 52 | Examples: |
| 52 | the kernel and disk information contained within them will be processed | ||
| 53 | and modified for the xen host. The kernel and guest image will be | ||
| 54 | copied to the appropriate location, and the config made to match. | ||
| 55 | 53 | ||
| 56 | These files following the naming convention: xen-guest-bundle*.cfg | 54 | # Single guest with autostart (default recommendation) |
| 55 | BUNDLED_XEN_GUESTS = "xen-guest-image-minimal:autostart" | ||
| 57 | 56 | ||
| 58 | Guests of type #1 generate a configuration file that is picked up as | 57 | # Guest without autostart |
| 59 | type #2. | 58 | BUNDLED_XEN_GUESTS = "xen-guest-image-minimal" |
| 60 | 59 | ||
| 61 | An example config file follows: | 60 | # External/3rd-party guest (no build dependency) |
| 61 | BUNDLED_XEN_GUESTS = "my-vendor-guest:external" | ||
| 62 | 62 | ||
| 63 | name = "xen-guest" | 63 | Per-guest configuration via varflags: |
| 64 | memory = 512 | ||
| 65 | vcpus = 1 | ||
| 66 | disk = ['file:xen-guest-image-minimal-qemuarm64.rootfs.ext4,xvda,rw'] | ||
| 67 | vif = ['bridge=xenbr0'] | ||
| 68 | kernel = "Image" | ||
| 69 | extra = "root=/dev/xvda ro console=hvc0 ip=dhcp" | ||
| 70 | 64 | ||
| 71 | It should also be noted that when a xen-guest-image-minimal is built | 65 | XEN_GUEST_MEMORY[xen-guest-image-minimal] = "1024" |
| 72 | with the XEN_GUEST_AUTO_BUNDLE varaible set to True, a configuration | 66 | XEN_GUEST_VCPUS[xen-guest-image-minimal] = "2" |
| 73 | file for type #2 will be generated and the guest bundled automatically | 67 | XEN_GUEST_VIF[xen-guest-image-minimal] = "bridge=xenbr0" |
| 74 | when the host image is built. | 68 | XEN_GUEST_EXTRA[xen-guest-image-minimal] = "root=/dev/xvda ro console=hvc0 ip=dhcp" |
| 69 | |||
| 70 | Custom config file (replaces auto-generation): | ||
| 71 | |||
| 72 | SRC_URI += "file://my-custom-guest.cfg" | ||
| 73 | BUNDLED_XEN_GUESTS = "xen-guest-image-minimal:autostart" | ||
| 74 | XEN_GUEST_CONFIG_FILE[xen-guest-image-minimal] = "${UNPACKDIR}/my-custom-guest.cfg" | ||
| 75 | |||
| 76 | Explicit rootfs/kernel for external guests: | ||
| 77 | |||
| 78 | XEN_GUEST_ROOTFS[my-vendor-guest] = "vendor-rootfs.ext4" | ||
| 79 | XEN_GUEST_KERNEL[my-vendor-guest] = "vendor-kernel" | ||
| 80 | |||
| 81 | ### Package-based (xen-guest-bundle.bbclass) | ||
| 82 | |||
| 83 | For reusable guest sets, create a bundle recipe that inherits | ||
| 84 | `xen-guest-bundle`: | ||
| 85 | |||
| 86 | # recipes-extended/xen-guest-bundles/my-guests_1.0.bb | ||
| 87 | inherit xen-guest-bundle | ||
| 88 | |||
| 89 | XEN_GUEST_BUNDLES = "xen-guest-image-minimal:autostart" | ||
| 90 | XEN_GUEST_MEMORY[xen-guest-image-minimal] = "1024" | ||
| 91 | |||
| 92 | Then install the bundle in the host image: | ||
| 93 | |||
| 94 | IMAGE_INSTALL:append:pn-xen-image-minimal = " my-guests" | ||
| 95 | |||
| 96 | The bundle package includes rootfs, kernel, and config files. At | ||
| 97 | image time, `merge_installed_xen_bundles()` deploys them to the | ||
| 98 | same target locations as the variable-driven path. | ||
| 99 | |||
| 100 | Custom config files work the same way via SRC_URI + varflag: | ||
| 101 | |||
| 102 | SRC_URI += "file://my-custom-guest.cfg" | ||
| 103 | XEN_GUEST_CONFIG_FILE[xen-guest-image-minimal] = "${UNPACKDIR}/my-custom-guest.cfg" | ||
| 104 | |||
| 105 | See `example-xen-guest-bundle_1.0.bb` for a complete example. | ||
| 106 | |||
| 107 | ### 3rd-party guest import | ||
| 108 | |||
| 109 | The import system converts fetched source formats (tarballs, qcow2 images, | ||
| 110 | etc.) into Xen-ready disk images at build time. This is for guests that | ||
| 111 | are not built by Yocto (e.g., Alpine minirootfs, Debian cloud images). | ||
| 112 | |||
| 113 | Per-guest varflags control the import: | ||
| 114 | |||
| 115 | XEN_GUEST_SOURCE_TYPE[guest] = "rootfs_dir" # import handler type | ||
| 116 | XEN_GUEST_SOURCE_FILE[guest] = "alpine-rootfs" # file/dir in UNPACKDIR | ||
| 117 | XEN_GUEST_IMAGE_SIZE[guest] = "128" # target image size in MB | ||
| 118 | |||
| 119 | Built-in import types: | ||
| 120 | |||
| 121 | | Type | Input | Output | Tool | | ||
| 122 | |---|---|---|---| | ||
| 123 | | `rootfs_dir` | Extracted rootfs directory | ext4 image | `mkfs.ext4 -F -d` | | ||
| 124 | | `qcow2` | QCOW2 disk image | raw image | `qemu-img convert` | | ||
| 125 | | `ext4` | ext4 image file | ext4 (copy) | `cp` | | ||
| 126 | | `raw` | raw disk image | raw (copy) | `cp` | | ||
| 127 | |||
| 128 | Native tool dependencies are resolved automatically at parse time. | ||
| 129 | |||
| 130 | Kernel modes (per-guest via `XEN_GUEST_KERNEL` varflag): | ||
| 131 | |||
| 132 | - (not set): Shared host kernel from DEPLOY_DIR_IMAGE | ||
| 133 | - `"path"`: Custom kernel from UNPACKDIR or DEPLOY_DIR_IMAGE | ||
| 134 | - `"none"`: HVM guest, no kernel (omits kernel= from config) | ||
| 135 | |||
| 136 | Alpine example (`alpine-xen-guest-bundle_3.23.bb`): | ||
| 137 | |||
| 138 | inherit xen-guest-bundle | ||
| 139 | |||
| 140 | SRC_URI = "https://...alpine-minirootfs-${ALPINE_VERSION}-${ALPINE_ARCH}.tar.gz;subdir=alpine-rootfs" | ||
| 141 | |||
| 142 | XEN_GUEST_BUNDLES = "alpine:autostart:external" | ||
| 143 | XEN_GUEST_SOURCE_TYPE[alpine] = "rootfs_dir" | ||
| 144 | XEN_GUEST_SOURCE_FILE[alpine] = "alpine-rootfs" | ||
| 145 | XEN_GUEST_IMAGE_SIZE[alpine] = "128" | ||
| 146 | XEN_GUEST_MEMORY[alpine] = "256" | ||
| 147 | XEN_GUEST_EXTRA[alpine] = "root=/dev/xvda ro console=hvc0" | ||
| 148 | |||
| 149 | Adding custom import types: define a shell function | ||
| 150 | `xen_guest_import_<type>(source_path, output_path, size_mb)` in a | ||
| 151 | bbclass, recipe, or bbappend and set the corresponding | ||
| 152 | `XEN_GUEST_IMPORT_DEPENDS_<type>` variable for native tool dependencies. | ||
| 153 | |||
| 154 | Target layout | ||
| 155 | ------------- | ||
| 75 | 156 | ||
| 76 | kernel and rootfs are copied to the target in /var/lib/xen/images/ | 157 | kernel and rootfs are copied to the target in /var/lib/xen/images/ |
| 77 | 158 | ||
| 78 | configuration files are copied to: /etc/xen | 159 | configuration files are copied to: /etc/xen |
| 79 | 160 | ||
| 80 | Guests can be launched after boot with: xl create -c /etc/xen/<config file> | 161 | autostart symlinks are created in: /etc/xen/auto/ |
| 162 | |||
| 163 | Guests can be launched after boot with: xl create -c /etc/xen/<guest>.cfg | ||
| 81 | 164 | ||
| 82 | Build and boot | 165 | Build and boot |
| 83 | -------------- | 166 | -------------- |
| 84 | 167 | ||
| 85 | Using a reference qmeuarm64 MACHINE, the following are the commands | 168 | Using a reference qemuarm64 MACHINE, the following are the commands |
| 86 | to build and boot a guest. | 169 | to build and boot a guest. |
| 87 | 170 | ||
| 88 | local.conf contains: | 171 | local.conf contains: |
| 89 | 172 | ||
| 90 | XEN_BUNDLED_GUESTS = "xen-guest-image-minimal-qemuarm64.rootfs.ext4:Image" | 173 | BUNDLED_XEN_GUESTS = "xen-guest-image-minimal:autostart" |
| 91 | 174 | ||
| 92 | % bitbake xen-guest-image-minimal | 175 | % bitbake xen-guest-image-minimal |
| 93 | % bitbake xen-image-minimal | 176 | % bitbake xen-image-minimal |
| 94 | 177 | ||
| 95 | % runqemu qemuarm64 nographic slirp qemuparams="-m 4096" tmp/deploy/images/qemuarm64/xen-image-minimal-qemuarm64.rootfs.ext4 | 178 | % runqemu qemuarm64 nographic slirp qemuparams="-m 4096" |
| 96 | 179 | ||
| 97 | Poky (Yocto Project Reference Distro) 5.1 qemuarm64 hvc0 | 180 | Poky (Yocto Project Reference Distro) 5.1 qemuarm64 hvc0 |
| 98 | 181 | ||
| 99 | qemuarm64 login: root | 182 | qemuarm64 login: root |
| 100 | 183 | ||
| 101 | WARNING: Poky is a reference Yocto Project distribution that should be used for | ||
| 102 | testing and development purposes only. It is recommended that you create your | ||
| 103 | own distribution for production use. | ||
| 104 | |||
| 105 | root@qemuarm64:~# uname -a | ||
| 106 | Linux qemuarm64 6.10.11-yocto-standard #1 SMP PREEMPT Fri Sep 20 22:32:26 UTC 2024 aarch64 GNU/Linux | ||
| 107 | root@qemuarm64:~# ls /etc/xen/ | 184 | root@qemuarm64:~# ls /etc/xen/ |
| 108 | auto | 185 | auto |
| 109 | cpupool | 186 | cpupool |
| 110 | scripts | 187 | scripts |
| 111 | xen-guest-bundle-xen-guest-image-minimal-qemuarm64--20241112174803.cfg | 188 | xen-guest-image-minimal.cfg |
| 112 | xl.conf | 189 | xl.conf |
| 113 | root@qemuarm64:~# ls /var/lib/xen/images/ | 190 | root@qemuarm64:~# ls /var/lib/xen/images/ |
| 114 | Image--6.10.11+git0+4bf82718cf_6c956b2ea6-r0-qemuarm64-20241018190311.bin | 191 | Image--6.10.11+git0+4bf82718cf_6c956b2ea6-r0-qemuarm64-20241018190311.bin |
| 115 | xen-guest-image-minimal-qemuarm64.rootfs-20241111222814.ext4 | 192 | xen-guest-image-minimal-qemuarm64-20241111222814.ext4 |
| 116 | |||
| 117 | root@qemuarm64:~# ip a s | ||
| 118 | 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000 | ||
| 119 | link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 | ||
| 120 | inet 127.0.0.1/8 scope host lo | ||
| 121 | valid_lft forever preferred_lft forever | ||
| 122 | inet6 ::1/128 scope host noprefixroute | ||
| 123 | valid_lft forever preferred_lft forever | ||
| 124 | 2: enp0s1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master xenbr0 qlen 1000 | ||
| 125 | link/ether 52:54:00:12:35:02 brd ff:ff:ff:ff:ff:ff | ||
| 126 | 3: sit0@NONE: <NOARP> mtu 1480 qdisc noop qlen 1000 | ||
| 127 | link/sit 0.0.0.0 brd 0.0.0.0 | ||
| 128 | 4: xenbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue qlen 1000 | ||
| 129 | link/ether ee:e4:a8:24:24:e7 brd ff:ff:ff:ff:ff:ff | ||
| 130 | inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic xenbr0 | ||
| 131 | valid_lft 86354sec preferred_lft 86354sec | ||
| 132 | inet6 fec0::ece4:a8ff:fe24:24e7/64 scope site dynamic noprefixroute flags 100 | ||
| 133 | valid_lft 86356sec preferred_lft 14356sec | ||
| 134 | inet6 fe80::ece4:a8ff:fe24:24e7/64 scope link | ||
| 135 | valid_lft forever preferred_lft forever | ||
| 136 | |||
| 137 | root@qemuarm64:~# xl create -c /etc/xen/xen-guest-bundle-xen-guest-image-minimal-qemuarm64--20241112174803.cfg | ||
| 138 | 193 | ||
| 139 | qemuarm64 login: root | 194 | root@qemuarm64:~# xl create -c /etc/xen/xen-guest-image-minimal.cfg |
| 140 | 195 | ||
| 141 | WARNING: Poky is a reference Yocto Project distribution that should be used for | 196 | qemuarm64 login: root |
| 142 | testing and development purposes only. It is recommended that you create your | ||
| 143 | own distribution for production use. | ||
| 144 | 197 | ||
| 145 | root@qemuarm64:~# uname -a | 198 | root@qemuarm64:~# uname -a |
| 146 | Linux qemuarm64 6.10.11-yocto-standard #1 SMP PREEMPT Fri Sep 20 22:32:26 UTC 2024 aarch64 GNU/Linux | 199 | Linux qemuarm64 6.10.11-yocto-standard #1 SMP PREEMPT Fri Sep 20 22:32:26 UTC 2024 aarch64 GNU/Linux |
| 147 | 200 | ||
| 148 | root@qemuarm64:~# wget example.com | ||
| 149 | Connecting to example.com (93.184.215.14:80) | ||
| 150 | wget: can't open 'index.html': File exists | ||
| 151 | root@qemuarm64:~# rm index.html | ||
| 152 | root@qemuarm64:~# wget example.com | ||
| 153 | Connecting to example.com (93.184.215.14:80) | ||
| 154 | saving to 'index.html' | ||
| 155 | index.html 100% |********************************| 1256 0:00:00 ETA | ||
| 156 | 'index.html' saved | ||
| 157 | |||
| 158 | From the host: | 201 | From the host: |
| 159 | 202 | ||
| 160 | Connection to 127.0.0.1 closed. | ||
| 161 | build4 [/home/bruc.../qemuarm64]> ssh -p 2222 root@127.0.0.1 | ||
| 162 | Last login: Tue Nov 12 20:42:57 2024 from 10.0.2.2 | ||
| 163 | |||
| 164 | WARNING: Poky is a reference Yocto Project distribution that should be used for | ||
| 165 | testing and development purposes only. It is recommended that you create your | ||
| 166 | own distribution for production use. | ||
| 167 | |||
| 168 | root@qemuarm64:~# xl list | 203 | root@qemuarm64:~# xl list |
| 169 | Name ID Mem VCPUs State Time(s) | 204 | Name ID Mem VCPUs State Time(s) |
| 170 | Domain-0 0 192 4 r----- 696.2 | 205 | Domain-0 0 192 4 r----- 696.2 |
| 171 | xen-guest 1 512 1 -b---- 153.0 | 206 | xen-guest-image-minimal 1 512 1 -b---- 153.0 |
| 172 | root@qemuarm64:~# xl destroy xen-guest | 207 | root@qemuarm64:~# xl destroy xen-guest-image-minimal |
| 173 | |||
