summaryrefslogtreecommitdiff
diff options
authorCorey Bryant <corey.bryant@canonical.com>2023-06-08 16:53:16 -0400
committerCorey Bryant <corey.bryant@canonical.com>2023-06-08 16:53:16 -0400
commitb46e1e668afeb37d8d4aece047fdf469bb08c4a4 (patch)
tree3afd72a62d97414759ee62ec08ab10ea18c42d74
parent135442e291e8c2cab38e33127935d87af94cbcf6 (diff)
New upstream version 3.29.03.29.0upstream-flamingoupstream
-rw-r--r--.zuul.d/jobs.yaml17
-rw-r--r--.zuul.d/project.yaml28
-rw-r--r--AUTHORS5
-rw-r--r--ChangeLog43
-rw-r--r--PKG-INFO2
-rw-r--r--diskimage_builder.egg-info/PKG-INFO2
-rw-r--r--diskimage_builder.egg-info/SOURCES.txt25
-rw-r--r--diskimage_builder.egg-info/entry_points.txt1
-rw-r--r--diskimage_builder.egg-info/pbr.json2
-rw-r--r--diskimage_builder.egg-info/requires.txt1
-rw-r--r--diskimage_builder/block_device/blockdevice.py14
-rw-r--r--diskimage_builder/block_device/level2/mkfs.py17
-rw-r--r--diskimage_builder/block_device/level3/mount.py46
-rw-r--r--diskimage_builder/block_device/level4/fstab.py9
-rw-r--r--diskimage_builder/block_device/tests/config/lvm_tree_partition_ordering.yaml28
-rw-r--r--diskimage_builder/block_device/tests/config/multiple_partitions_graph.yaml48
-rw-r--r--diskimage_builder/block_device/tests/config/multiple_partitions_tree.yaml81
-rw-r--r--diskimage_builder/block_device/tests/test_mount_order.py16
-rw-r--r--diskimage_builder/diskimage_builder.py574
-rwxr-xr-xdiskimage_builder/elements/bootloader/finalise.d/50-bootloader48
-rw-r--r--diskimage_builder/elements/cache-url/README.rst6
-rw-r--r--diskimage_builder/elements/cache-url/pkg-map5
-rwxr-xr-xdiskimage_builder/elements/centos/pre-install.d/00-02-set-centos-mirror6
-rw-r--r--diskimage_builder/elements/cloud-init-growpart/README.rst22
-rw-r--r--diskimage_builder/elements/cloud-init-growpart/element-deps2
-rw-r--r--diskimage_builder/elements/cloud-init-growpart/package-installs.yaml1
-rw-r--r--diskimage_builder/elements/cloud-init-growpart/pkg-map10
-rwxr-xr-xdiskimage_builder/elements/cloud-init-growpart/post-install.d/55-growpart25
-rw-r--r--diskimage_builder/elements/cloud-init-growpart/releasenotes/notes/added_growpart_for_lvm-0ce76ba71710c720.yaml7
-rwxr-xr-xdiskimage_builder/elements/containerfile/root.d/08-containerfile7
-rw-r--r--diskimage_builder/elements/fedora-container/containerfiles/373
-rw-r--r--diskimage_builder/elements/fedora/environment.d/10-fedora-distro-name.bash2
-rwxr-xr-xdiskimage_builder/elements/fedora/root.d/10-fedora-cloud-image3
-rw-r--r--diskimage_builder/elements/fips/README.rst24
-rw-r--r--diskimage_builder/elements/fips/package-installs.yaml14
-rwxr-xr-xdiskimage_builder/elements/fips/pre-install.d/01-setup-fips34
-rwxr-xr-xdiskimage_builder/elements/growvols/static/usr/local/sbin/growvols60
-rw-r--r--diskimage_builder/elements/growvols/tests/test_growvols.py41
-rwxr-xr-x[-rw-r--r--]diskimage_builder/elements/openeuler-minimal/pre-install.d/00-setup-mirror (renamed from diskimage_builder/elements/openeuler-minimal/pre-install.d/00-setup-mirror.bash)8
-rw-r--r--diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/README.rst1
-rw-r--r--diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/element-deps3
-rw-r--r--diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/environment.d/09-set-distro.bash1
-rwxr-xr-xdiskimage_builder/elements/sysprep/bin/extract-image6
-rwxr-xr-xdiskimage_builder/elements/ubuntu-common/post-install.d/99-autoremove (renamed from diskimage_builder/elements/ubuntu/post-install.d/99-autoremove)0
-rw-r--r--diskimage_builder/elements/yum-minimal/pkg-map29
-rw-r--r--diskimage_builder/elements/yum/README.rst36
-rwxr-xr-xdiskimage_builder/elements/yum/pre-install.d/01-00-centos-python32
-rw-r--r--diskimage_builder/lib/disk-image-create5
-rw-r--r--diskimage_builder/lib/ramdisk-image-create5
-rw-r--r--diskimage_builder/tests/test_diskimage_builder.py587
-rw-r--r--doc/source/developer/components.rst54
-rw-r--r--doc/source/user_guide/building_an_image.rst25
-rw-r--r--doc/source/user_guide/installation.rst4
-rw-r--r--lower-constraints.txt1
-rw-r--r--releasenotes/notes/Fix-ubuntu-minimal-not-running-autoremove-7a4e31de2a525f46.yaml5
-rw-r--r--releasenotes/notes/add-fips-element-a5a3e0e3c653f923.yaml12
-rw-r--r--releasenotes/notes/containerfile-host-networking-0691f3be5c6b11b6.yaml6
-rw-r--r--releasenotes/notes/dib-command-a190f41cbd572b4b.yaml8
-rw-r--r--releasenotes/notes/fix-grub-boot-kernel-commandline-1f94e49884c517c0.yaml10
-rw-r--r--releasenotes/notes/swap_support-9ac267f56a0c0424.yaml4
-rw-r--r--requirements.txt1
-rw-r--r--setup.cfg1
-rwxr-xr-xtests/run_functests.sh53
-rw-r--r--tox.ini4
64 files changed, 1950 insertions, 200 deletions
diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml
index d73765c..3e4581b 100644
--- a/.zuul.d/jobs.yaml
+++ b/.zuul.d/jobs.yaml
@@ -61,6 +61,7 @@
- centos-minimal/8-stream-aarch64-build-succeeds
- centos-minimal/9-stream-aarch64-build-succeeds
- openeuler-minimal/22.03-LTS-build-succeeds
+ - rocky-container/rocky-9-aarch64-build-succeeds
#
# Build and boot functional tests
@@ -119,7 +120,7 @@
# mirror: "http://{{ zuul_site_mirror_fqdn }}/centos"
- job:
- name: dib-nodepool-functional-openstack-fedora-36-containerfile-src
+ name: dib-nodepool-functional-openstack-fedora-37-containerfile-src
description: |
Test building and booting an Fedora image from a
containerfile with Nodepool and OpenStack (using released
@@ -129,11 +130,7 @@
nodepool_debug: true
nodepool_diskimage:
base_element : fedora-container
- release: '36'
- # NOTE(ianw) 2022-07-11 : something in jammy has broken running
- # podman inside docker. Investigations continue, but force this
- # back for now.
- nodeset: ubuntu-focal
+ release: '37'
- job:
name: dib-nodepool-functional-openstack-rockylinux-8-containerfile-src
@@ -147,10 +144,6 @@
nodepool_diskimage:
base_element: rocky-container
release: '8'
- # NOTE(ianw) 2022-07-11 : something in jammy has broken running
- # podman inside docker. Investigations continue, but force this
- # back for now.
- nodeset: ubuntu-focal
- job:
name: dib-nodepool-functional-openstack-rockylinux-9-containerfile-src
@@ -164,10 +157,6 @@
nodepool_diskimage:
base_element: rocky-container
release: '9'
- # NOTE(ianw) 2022-07-11 : something in jammy has broken running
- # podman inside docker. Investigations continue, but force this
- # back for now.
- nodeset: ubuntu-focal
- job:
name: dib-nodepool-functional-openstack-ubuntu-xenial-src
diff --git a/.zuul.d/project.yaml b/.zuul.d/project.yaml
index 274cca1..aaeace9 100644
--- a/.zuul.d/project.yaml
+++ b/.zuul.d/project.yaml
@@ -15,8 +15,16 @@
nodes:
- name: ubuntu-bionic
label: ubuntu-bionic
- - tox-py38
- - tox-py39
+ - tox-py38:
+ nodeset:
+ nodes:
+ - name: ubuntu-focal
+ label: ubuntu-focal
+ - tox-py39:
+ nodeset:
+ nodes:
+ - name: ubuntu-focal
+ label: ubuntu-focal
- tox-py310:
nodeset:
nodes:
@@ -28,7 +36,7 @@
- dib-nodepool-functional-openstack-centos-7-src
- dib-nodepool-functional-openstack-centos-8-stream-src
- dib-nodepool-functional-openstack-centos-9-stream-src
- - dib-nodepool-functional-openstack-fedora-36-containerfile-src
+ - dib-nodepool-functional-openstack-fedora-37-containerfile-src
- dib-nodepool-functional-openstack-rockylinux-8-containerfile-src:
voting: false
- dib-nodepool-functional-openstack-rockylinux-9-containerfile-src:
@@ -61,8 +69,16 @@
nodes:
- name: ubuntu-bionic
label: ubuntu-bionic
- - tox-py38
- - tox-py39
+ - tox-py38:
+ nodeset:
+ nodes:
+ - name: ubuntu-focal
+ label: ubuntu-focal
+ - tox-py39:
+ nodeset:
+ nodes:
+ - name: ubuntu-focal
+ label: ubuntu-focal
- tox-py310:
nodeset:
nodes:
@@ -73,7 +89,7 @@
- dib-nodepool-functional-openstack-centos-7-src
- dib-nodepool-functional-openstack-centos-8-stream-src
- dib-nodepool-functional-openstack-centos-9-stream-src
- - dib-nodepool-functional-openstack-fedora-36-containerfile-src
+ - dib-nodepool-functional-openstack-fedora-37-containerfile-src
- dib-nodepool-functional-openstack-ubuntu-xenial-src
- dib-nodepool-functional-openstack-ubuntu-bionic-src
- dib-nodepool-functional-openstack-ubuntu-focal-src
diff --git a/AUTHORS b/AUTHORS
index 0b9fa8c..6314e68 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -87,6 +87,7 @@ Dustin J. Mitchell <dustin@v.igoro.us>
Eduardo Santos <eduardo.experimental@gmail.com>
Emilien Macchi <emilien@redhat.com>
Endre Karlson <endre.karlson@hp.com>
+Erik Berg <openstack@slipsprogrammor.no>
Erno Kuvaja <jokke@usr.fi>
Erwan Velu <erwan@enovance.com>
Ethan Gafford <egafford@redhat.com>
@@ -95,6 +96,7 @@ Fatih Degirmenci <fdegir@gmail.com>
Felipe Alencastro <felipe@alencastro.org>
Francois RIGAULT <rigault.francois@gmail.com>
Frederic Lepied <frederic.lepied@enovance.com>
+Frikin Evgenii <frikin.evgenii@huawei.com>
Gabriele Cerami <gcerami@redhat.com>
Gary Duan <duanlg@live.cn>
Gaƫtan Trellu <gaetan.trellu@incloudus.com>
@@ -147,6 +149,7 @@ Jiri Stransky <jistr@redhat.com>
Joe Gordon <joe.gordon0@gmail.com>
Joey D <jobewan@gmail.com>
John L. Villalovos <john.l.villalovos@intel.com>
+John L. Villalovos <openstack.org@sodarock.com>
John Trowbridge <trown@redhat.com>
Jon-Paul Sullivan <jonpaul.sullivan@hp.com>
Jonas Sticha <jonas.sticha@bmw-carit.de>
@@ -295,6 +298,7 @@ Tristan Cacqueray <tdecacqu@redhat.com>
Tristan Cacqueray <tristan.cacqueray@enovance.com>
Uwe Grawert <uwe.grawert@csc.fi>
Van Hung Pham <hungpv@vn.fujitsu.com>
+Vanou Ishii <ishii.vanou@fujitsu.com>
Victor Lowther <victor.lowther@gmail.com>
Vipul Sabhaya <vipuls@gmail.com>
Vu Cong Tuan <tuanvc@vn.fujitsu.com>
@@ -331,6 +335,7 @@ iberezovskiy <iberezovskiy@mirantis.com>
inspurericzhang <zhanglf01@inspur.com>
jacky06 <zhang.min@99cloud.net>
janonymous <janonymous.codevulture@gmail.com>
+jgupta <jayadityagupta11@gmail.com>
jodewey <jodewey@cisco.com>
justin-hopper <justin.hopper@hp.com>
kaiokassiano <kaiokmo@lsd.ufcg.edu.br>
diff --git a/ChangeLog b/ChangeLog
index e63fcba..ed9dbfe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,48 @@
CHANGES
=======
+3.29.0
+------
+
+* Rename openeuler mirror script
+* Check and grow the GPT structure to the end of the volume
+
+3.28.0
+------
+
+* Fix jsonschema version to match lower-constraint
+* Fix openeuler mirror problem
+* Fix ubuntu-minimal to run autoremove
+* Add a FIPS element
+
+3.27.0
+------
+
+* Correct boot path to cover FIPS usage cases
+* Update Fedora to 37
+* Removal focal pins for testing
+* Document diskimage-builder command
+* Switch run\_functests.sh from disk-image-create to diskimage-builder
+* A new diskimage-builder command for yaml image builds
+* chore: support building Fedora on arm64 AKA aarch64
+* Add swap support
+* Fix double-keyed json
+* Repeat to umount filesystem when exception occurs
+
+3.26.0
+------
+
+* cache-url: Give up on curl install for Redhat platforms
+* Clean up tox.ini for tox v4
+* Reduce thin pool by one more extent
+* Grow thin pool metadata by 1GiB
+* Add variable for check installing python3 in yum element
+* tox jobs: pin to correct nodesets; use host networking for containerfile
+* Fix issue in extract image
+* Added example configuration
+* Added cloud-init growpart element
+* Add Rocky 9 ARM64 functional test
+
3.25.0
------
@@ -22,6 +64,7 @@ CHANGES
* rocky : create machine-id in 9
* Allow setting ROOT\_LABEL from environment
* Do dmsetup remove device in rollback
+* Fix wrong yum.conf name of CentOS 9 Stream
3.23.0
------
diff --git a/PKG-INFO b/PKG-INFO
index f4a0d1a..5b83273 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.2
Name: diskimage-builder
-Version: 3.25.0
+Version: 3.29.0
Summary: Golden Disk Image builder.
Home-page: https://docs.openstack.org/diskimage-builder/latest/
Author: OpenStack
diff --git a/diskimage_builder.egg-info/PKG-INFO b/diskimage_builder.egg-info/PKG-INFO
index f4a0d1a..5b83273 100644
--- a/diskimage_builder.egg-info/PKG-INFO
+++ b/diskimage_builder.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.2
Name: diskimage-builder
-Version: 3.25.0
+Version: 3.29.0
Summary: Golden Disk Image builder.
Home-page: https://docs.openstack.org/diskimage-builder/latest/
Author: OpenStack
diff --git a/diskimage_builder.egg-info/SOURCES.txt b/diskimage_builder.egg-info/SOURCES.txt
index f7d1929..6aeb028 100644
--- a/diskimage_builder.egg-info/SOURCES.txt
+++ b/diskimage_builder.egg-info/SOURCES.txt
@@ -16,6 +16,7 @@ tox.ini
bin/dib-lint
diskimage_builder/__init__.py
diskimage_builder/disk_image_create.py
+diskimage_builder/diskimage_builder.py
diskimage_builder/element_dependencies.py
diskimage_builder/logging_config.py
diskimage_builder/paths.py
@@ -199,6 +200,12 @@ diskimage_builder/elements/cloud-init-datasources/install.d/05-set-cloud-init-so
diskimage_builder/elements/cloud-init-disable-resizefs/README.rst
diskimage_builder/elements/cloud-init-disable-resizefs/post-install.d/50-cloud-init-disable-resizefs
diskimage_builder/elements/cloud-init-disable-resizefs/post-install.d/51-cloud-init-disable-growpart
+diskimage_builder/elements/cloud-init-growpart/README.rst
+diskimage_builder/elements/cloud-init-growpart/element-deps
+diskimage_builder/elements/cloud-init-growpart/package-installs.yaml
+diskimage_builder/elements/cloud-init-growpart/pkg-map
+diskimage_builder/elements/cloud-init-growpart/post-install.d/55-growpart
+diskimage_builder/elements/cloud-init-growpart/releasenotes/notes/added_growpart_for_lvm-0ce76ba71710c720.yaml
diskimage_builder/elements/cloud-init-nocloud/README.rst
diskimage_builder/elements/cloud-init-nocloud/element-deps
diskimage_builder/elements/cloud-init-nocloud/environment.d/10-cloud-init-nocloud.bash
@@ -393,6 +400,7 @@ diskimage_builder/elements/fedora-container/pkg-map
diskimage_builder/elements/fedora-container/containerfiles/34
diskimage_builder/elements/fedora-container/containerfiles/35
diskimage_builder/elements/fedora-container/containerfiles/36
+diskimage_builder/elements/fedora-container/containerfiles/37
diskimage_builder/elements/fedora-container/environment.d/10-01-fedora-distro-name.bash
diskimage_builder/elements/fedora-container/environment.d/11-yum-dnf.bash
diskimage_builder/elements/fedora-container/test-elements/build-succeeds/README.rst
@@ -411,6 +419,9 @@ diskimage_builder/elements/fedora/pre-install.d/00-02-set-fedora-mirror
diskimage_builder/elements/fedora/pre-install.d/02-set-machine-id
diskimage_builder/elements/fedora/root.d/10-fedora-cloud-image
diskimage_builder/elements/fedora/test-elements/build-succeeds/element-deps
+diskimage_builder/elements/fips/README.rst
+diskimage_builder/elements/fips/package-installs.yaml
+diskimage_builder/elements/fips/pre-install.d/01-setup-fips
diskimage_builder/elements/gentoo/README.rst
diskimage_builder/elements/gentoo/element-deps
diskimage_builder/elements/gentoo/element-provides
@@ -556,7 +567,7 @@ diskimage_builder/elements/openeuler-minimal/element-provides
diskimage_builder/elements/openeuler-minimal/package-installs.yaml
diskimage_builder/elements/openeuler-minimal/environment.d/10-openeuler-distro-name.bash
diskimage_builder/elements/openeuler-minimal/environment.d/11-yum-dnf.bash
-diskimage_builder/elements/openeuler-minimal/pre-install.d/00-setup-mirror.bash
+diskimage_builder/elements/openeuler-minimal/pre-install.d/00-setup-mirror
diskimage_builder/elements/openeuler-minimal/root.d/00-00-generate-repo
diskimage_builder/elements/openeuler-minimal/test-elements/22.03-LTS-build-succeeds/README.rst
diskimage_builder/elements/openeuler-minimal/test-elements/22.03-LTS-build-succeeds/element-deps
@@ -716,6 +727,9 @@ diskimage_builder/elements/rocky-container/environment.d/10-01-rocky-distro-name
diskimage_builder/elements/rocky-container/environment.d/11-yum-dnf.bash
diskimage_builder/elements/rocky-container/test-elements/build-succeeds/README.rst
diskimage_builder/elements/rocky-container/test-elements/build-succeeds/element-deps
+diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/README.rst
+diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/element-deps
+diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/environment.d/09-set-distro.bash
diskimage_builder/elements/rpm-distro/README.rst
diskimage_builder/elements/rpm-distro/cleanup.d/99-selinux-fixfiles-restore
diskimage_builder/elements/rpm-distro/post-install.d/06-network-config-nonzeroconf
@@ -796,6 +810,7 @@ diskimage_builder/elements/ubuntu-common/element-deps
diskimage_builder/elements/ubuntu-common/environment.d/10-ubuntu-distro-name.bash
diskimage_builder/elements/ubuntu-common/environment.d/11-ubuntu-init-system.bash
diskimage_builder/elements/ubuntu-common/install.d/80-disable-rfc3041
+diskimage_builder/elements/ubuntu-common/post-install.d/99-autoremove
diskimage_builder/elements/ubuntu-minimal/README.rst
diskimage_builder/elements/ubuntu-minimal/element-deps
diskimage_builder/elements/ubuntu-minimal/element-provides
@@ -850,7 +865,6 @@ diskimage_builder/elements/ubuntu-systemd-container/test-elements/xenial-build-s
diskimage_builder/elements/ubuntu-systemd-container/test-elements/xenial-build-succeeds/test-output-formats
diskimage_builder/elements/ubuntu-systemd-container/test-elements/xenial-build-succeeds/environment.d/10-set-distro.bash
diskimage_builder/elements/ubuntu/environment.d/99-cloud-init-datasources.bash
-diskimage_builder/elements/ubuntu/post-install.d/99-autoremove
diskimage_builder/elements/ubuntu/pre-install.d/00-remove-apt-xapian-index
diskimage_builder/elements/ubuntu/pre-install.d/01-set-ubuntu-mirror
diskimage_builder/elements/ubuntu/root.d/10-cache-ubuntu-tarball
@@ -934,6 +948,7 @@ diskimage_builder/lib/ramdisk-functions
diskimage_builder/lib/ramdisk-image-create
diskimage_builder/tests/__init__.py
diskimage_builder/tests/base.py
+diskimage_builder/tests/test_diskimage_builder.py
diskimage_builder/tests/test_elementdeps.py
diskimage_builder/tests/test_loggingconfig.py
diskimage_builder/tests/test_no_dup_filenames.py
@@ -970,10 +985,12 @@ releasenotes/notes/1.17.0-ef744f36d277dba4.yaml
releasenotes/notes/1.18.0-4433d3076627f10d.yaml
releasenotes/notes/1.18.1-ceeb514708dcb731.yaml
releasenotes/notes/Add-DIB-UBUNTU-KERNEL-5f75a809f3ce9bab.yaml
+releasenotes/notes/Fix-ubuntu-minimal-not-running-autoremove-7a4e31de2a525f46.yaml
releasenotes/notes/add-6b94d90caea2895e.yaml
releasenotes/notes/add-aarch64-support-for-rhel-c62a0e02b1ad9033.yaml
releasenotes/notes/add-centos-8-support-4fd28eb04e11ba43.yaml
releasenotes/notes/add-efi-packages-70a19464d31ab8d7.yaml
+releasenotes/notes/add-fips-element-a5a3e0e3c653f923.yaml
releasenotes/notes/add-grub2-efi-x64-modules-for-centos-9-74401ca5ec8201c7.yaml
releasenotes/notes/add-modprobe-element-8e3b0287ebb11920.yaml
releasenotes/notes/add-openeuler-minimal-element-068dc7d9d94e5098.yaml
@@ -993,6 +1010,7 @@ releasenotes/notes/centos-minimal-8-aca6314862741177.yaml
releasenotes/notes/centos-minimal-8-stream-97021a2c92463dde.yaml
releasenotes/notes/centos-retired-f17ae9f6f03e57e3.yaml
releasenotes/notes/cloud-init-resizefs-growpart-e820b8c7f3adb78b.yaml
+releasenotes/notes/containerfile-host-networking-0691f3be5c6b11b6.yaml
releasenotes/notes/containerfile-root-extraction-430148dd669cb3da.yaml
releasenotes/notes/create-945440b17d500bf5.yaml
releasenotes/notes/dash-p-after-install-58a87549c1c906c3.yaml
@@ -1004,6 +1022,7 @@ releasenotes/notes/dhcp-all-interfaces-add-opt-to-let-NetworkManager-handle-it-f
releasenotes/notes/dhcp-all-interfaces-debian-issue-2ec7f1a5186f0b16.yaml
releasenotes/notes/dhcp-all-interfaces-networkmanager-b34f2fc8fb1a678f.yaml
releasenotes/notes/dhcp-vlan-interfaces-b34ab224b9431e3a.yaml
+releasenotes/notes/dib-command-a190f41cbd572b4b.yaml
releasenotes/notes/dib-distribution-mirror-8c241c0d3d4a539a.yaml
releasenotes/notes/dib-init-system-5647bad17a01c602.yaml
releasenotes/notes/dib-init-system_fix_for_debian_jessie-c6f7261ee84dad27.yaml
@@ -1024,6 +1043,7 @@ releasenotes/notes/ensure-venv-d7c16a2a04fd3b8f.yaml
releasenotes/notes/fedora26-690b9fd9ac3c3d4f.yaml
releasenotes/notes/fedora32-9dfa4d9d4dcce1ff.yaml
releasenotes/notes/fix-and-update-opensuse-15.3-c7fee120b51e3621.yaml
+releasenotes/notes/fix-grub-boot-kernel-commandline-1f94e49884c517c0.yaml
releasenotes/notes/fix_rdisc6_loop-32a308a97de99f0f.yaml
releasenotes/notes/gpt-esp-partition-size-200568cb6fcc8788.yaml
releasenotes/notes/grub-timeout-1cdd14a2b1467d89.yaml
@@ -1071,6 +1091,7 @@ releasenotes/notes/skip-packages-env-c97e7b4820f9bfda.yaml
releasenotes/notes/specify-bootstrap-packages-via-env-22f5c6982c09f16a.yaml
releasenotes/notes/squashfs-output-91c1f0dc37474d3c.yaml
releasenotes/notes/start-using-reno-446b3d52a467a273.yaml
+releasenotes/notes/swap_support-9ac267f56a0c0424.yaml
releasenotes/notes/sysfs-ro-b127a6df2d78e57c.yaml
releasenotes/notes/sysprep-f3fd036bc1d2c405.yaml
releasenotes/notes/sysprep-fixes-8890b968a8fa7ac1.yaml
diff --git a/diskimage_builder.egg-info/entry_points.txt b/diskimage_builder.egg-info/entry_points.txt
index 8d27eb0..ceae7bf 100644
--- a/diskimage_builder.egg-info/entry_points.txt
+++ b/diskimage_builder.egg-info/entry_points.txt
@@ -1,5 +1,6 @@
[console_scripts]
disk-image-create = diskimage_builder.disk_image_create:main
+diskimage-builder = diskimage_builder.diskimage_builder:main
ramdisk-image-create = diskimage_builder.disk_image_create:main
[diskimage_builder.block_device.plugin]
diff --git a/diskimage_builder.egg-info/pbr.json b/diskimage_builder.egg-info/pbr.json
index 347f5ec..3867b31 100644
--- a/diskimage_builder.egg-info/pbr.json
+++ b/diskimage_builder.egg-info/pbr.json
@@ -1 +1 @@
-{"git_version": "2a25db9e", "is_release": true} \ No newline at end of file
+{"git_version": "48cbe94e", "is_release": true} \ No newline at end of file
diff --git a/diskimage_builder.egg-info/requires.txt b/diskimage_builder.egg-info/requires.txt
index 3242ed0..671d7da 100644
--- a/diskimage_builder.egg-info/requires.txt
+++ b/diskimage_builder.egg-info/requires.txt
@@ -1,5 +1,6 @@
PyYAML>=3.12
flake8<6.0.0,>=3.6.0
+jsonschema>=3.0.2
networkx>=2.3.0
pbr!=2.1.0,>=2.0.0
stevedore>=1.20.0
diff --git a/diskimage_builder/block_device/blockdevice.py b/diskimage_builder/block_device/blockdevice.py
index 8b85931..99f23be 100644
--- a/diskimage_builder/block_device/blockdevice.py
+++ b/diskimage_builder/block_device/blockdevice.py
@@ -316,6 +316,20 @@ class BlockDevice(object):
print("%s" % root_fs['type'])
return 0
+ if symbol == "boot-label":
+ try:
+ boot_mount = self._config_get_mount("/boot")
+ boot_fs = self._config_get_mkfs(boot_mount['base'])
+ # If not explicitly defined, we appear to fallback
+ # to name for a label, which we can only get from the
+ # resulting filesystem config.
+ boot_label = boot_fs.get('label', boot_fs.get('name', ''))
+ except AssertionError:
+ boot_label = ''
+ logger.debug("boot-label [%s]", boot_label)
+ print("%s" % boot_label)
+ return 0
+
if symbol == 'mount-points':
mount_points = self._config_get_all_mount_points()
# we return the mountpoints joined by a pipe, because it is not
diff --git a/diskimage_builder/block_device/level2/mkfs.py b/diskimage_builder/block_device/level2/mkfs.py
index 1f62340..b7e957b 100644
--- a/diskimage_builder/block_device/level2/mkfs.py
+++ b/diskimage_builder/block_device/level2/mkfs.py
@@ -33,7 +33,8 @@ file_system_max_label_length = {
"ext3": 16,
"ext4": 16,
"xfs": 12,
- "vfat": 11
+ "vfat": 11,
+ "swap": 16
}
@@ -102,18 +103,20 @@ class FilesystemNode(NodeBase):
return (edge_from, edge_to)
def create(self):
- cmd = ["mkfs"]
-
- cmd.extend(['-t', self.type])
- if self.opts:
- cmd.extend(self.opts)
+ if self.type in ('swap'):
+ cmd = ["mkswap"]
+ else:
+ cmd = ["mkfs"]
+ cmd.extend(['-t', self.type])
+ if self.opts:
+ cmd.extend(self.opts)
if self.type in ('vfat', 'fat'):
cmd.extend(["-n", self.label])
else:
cmd.extend(["-L", self.label])
- if self.type in ('ext2', 'ext3', 'ext4'):
+ if self.type in ('ext2', 'ext3', 'ext4', 'swap'):
cmd.extend(['-U', self.uuid])
elif self.type == 'xfs':
cmd.extend(['-m', "uuid=%s" % self.uuid])
diff --git a/diskimage_builder/block_device/level3/mount.py b/diskimage_builder/block_device/level3/mount.py
index 963f12b..b21f8b6 100644
--- a/diskimage_builder/block_device/level3/mount.py
+++ b/diskimage_builder/block_device/level3/mount.py
@@ -15,6 +15,7 @@
import functools
import logging
import os
+import time
from diskimage_builder.block_device.exception \
import BlockDeviceSetupException
@@ -72,17 +73,21 @@ class MountPointNode(NodeBase):
return (edge_from, edge_to)
def create(self):
- logger.debug("mount called [%s]", self.mount_point)
- rel_mp = self.mount_point if self.mount_point[0] != '/' \
- else self.mount_point[1:]
- mount_point = os.path.join(self.mount_base, rel_mp)
- if not os.path.exists(mount_point):
- # Need to sudo this because of permissions in the new
- # file system tree.
- exec_sudo(['mkdir', '-p', mount_point])
- logger.info("Mounting [%s] to [%s]", self.name, mount_point)
- exec_sudo(["mount", self.state['filesys'][self.base]['device'],
- mount_point])
+ if (self.state['filesys'][self.base]['fstype'] == 'swap'):
+ # No need to mount/activate swap during image build.
+ mount_point = self.mount_point = 'none'
+ else:
+ logger.debug("mount called [%s]", self.mount_point)
+ rel_mp = self.mount_point if self.mount_point[0] != '/' \
+ else self.mount_point[1:]
+ mount_point = os.path.join(self.mount_base, rel_mp)
+ if not os.path.exists(mount_point):
+ # Need to sudo this because of permissions in the new
+ # file system tree.
+ exec_sudo(['mkdir', '-p', mount_point])
+ logger.info("Mounting [%s] to [%s]", self.name, mount_point)
+ exec_sudo(["mount", self.state['filesys'][self.base]['device'],
+ mount_point])
if 'mount' not in self.state:
self.state['mount'] = {}
@@ -94,6 +99,9 @@ class MountPointNode(NodeBase):
self.state['mount_order'].append(self.mount_point)
def umount(self):
+ if (self.state['filesys'][self.base]['fstype'] == 'swap'):
+ # Swap not mounted/activated during image build.
+ return
logger.info("Called for [%s]", self.name)
# Before calling umount, call 'fstrim' on suitable mounted
# file systems. This discards unused blocks from the mounted
@@ -109,7 +117,21 @@ class MountPointNode(NodeBase):
if self.state['filesys'][self.base]['fstype'] != 'vfat':
exec_sudo(["fstrim", "--verbose",
self.state['mount'][self.mount_point]['path']])
- exec_sudo(["umount", self.state['mount'][self.mount_point]['path']])
+ # Even 'fstrim' call sometimes don't solve the issue with 'busy'
+ # filesystem, so we need to catch the exception and repeat unount.
+ mount_point = self.state['mount'][self.mount_point]['path']
+ catch = None
+ for try_cnt in range(10, 1, -1):
+ try:
+ exec_sudo(["umount", mount_point])
+ return
+ except BlockDeviceSetupException as e:
+ catch = e
+ logger.error("umount failed (%s)", e.output.strip())
+ time.sleep(3)
+
+ logger.debug("Gave up trying to umount [%s]", mount_point)
+ raise catch
def delete(self):
self.umount()
diff --git a/diskimage_builder/block_device/level4/fstab.py b/diskimage_builder/block_device/level4/fstab.py
index 38f614d..cda8264 100644
--- a/diskimage_builder/block_device/level4/fstab.py
+++ b/diskimage_builder/block_device/level4/fstab.py
@@ -40,12 +40,15 @@ class FstabNode(NodeBase):
if 'fstab' not in self.state:
self.state['fstab'] = {}
+ swap = 'none' in self.state['mount'] and \
+ self.state['mount']['none']['name'] == self.base
+
self.state['fstab'][self.base] = {
'name': self.name,
'base': self.base,
- 'options': self.options,
- 'dump-freq': self.dump_freq,
- 'fsck-passno': self.fsck_passno
+ 'options': 'sw' if swap else self.options,
+ 'dump-freq': 0 if swap else self.dump_freq,
+ 'fsck-passno': 0 if swap else self.fsck_passno
}
diff --git a/diskimage_builder/block_device/tests/config/lvm_tree_partition_ordering.yaml b/diskimage_builder/block_device/tests/config/lvm_tree_partition_ordering.yaml
index 06526b8..e28da14 100644
--- a/diskimage_builder/block_device/tests/config/lvm_tree_partition_ordering.yaml
+++ b/diskimage_builder/block_device/tests/config/lvm_tree_partition_ordering.yaml
@@ -7,10 +7,10 @@
label: mbr
partitions:
- name: boot
- flags: [ boot,primary ]
+ flags: [boot, primary]
size: 1G
- name: root
- flags: [ primary ]
+ flags: [primary]
size: 3G
- lvm:
@@ -27,12 +27,16 @@
lvs:
- name: lv_root
base: vg
- size: 2000M
+ size: 1900M
- name: lv_var
base: vg
size: 500M
+ - name: lv_swap
+ base: vg
+ size: 100M
+
- mkfs:
base: boot
type: ext3
@@ -50,8 +54,8 @@
mount:
mount_point: /
fstab:
- options: "noacl,errors=remount-ro"
- fsck-passno: 1
+ options: "noacl,errors=remount-ro"
+ fsck-passno: 1
- mkfs:
name: mkfs_var
@@ -60,5 +64,15 @@
mount:
mount_point: /var
fstab:
- options: "noacl"
- fsck-passno: 2
+ options: "noacl"
+ fsck-passno: 2
+
+- mkfs:
+ name: mkfs_swap
+ base: lv_swap
+ type: "swap"
+ mount:
+ mount_point: none
+ fstab:
+ options: "sw"
+ fsck-passno: 0
diff --git a/diskimage_builder/block_device/tests/config/multiple_partitions_graph.yaml b/diskimage_builder/block_device/tests/config/multiple_partitions_graph.yaml
index fe262a2..1822a38 100644
--- a/diskimage_builder/block_device/tests/config/multiple_partitions_graph.yaml
+++ b/diskimage_builder/block_device/tests/config/multiple_partitions_graph.yaml
@@ -2,20 +2,23 @@
name: image0
- partitioning:
- base: image0
- name: mbr
- label: mbr
- partitions:
- - name: root
- base: image0
- flags: [ boot, primary ]
- size: 55%
- - name: var
- base: image0
- size: 40%
- - name: var_log
- base: image0
- size: 5%
+ base: image0
+ name: mbr
+ label: mbr
+ partitions:
+ - name: root
+ base: image0
+ flags: [boot, primary]
+ size: 54%
+ - name: var
+ base: image0
+ size: 40%
+ - name: var_log
+ base: image0
+ size: 5%
+ - name: swap
+ base: image0
+ size: 1%
- mkfs:
base: root
@@ -67,3 +70,20 @@
name: fstab_mount_mkfs_var_log
fsck-passno: 1
options: defaults
+
+- mkfs:
+ base: swap
+ name: mkfs_swap
+ type: swap
+ uuid: swap-uuid-1234
+
+- mount:
+ base: mkfs_swap
+ name: mount_mkfs_swap
+ mount_point: none
+
+- fstab:
+ base: mount_mkfs_swap
+ name: fstab_mount_mkfs_swap
+ fsck-passno: 0
+ options: sw
diff --git a/diskimage_builder/block_device/tests/config/multiple_partitions_tree.yaml b/diskimage_builder/block_device/tests/config/multiple_partitions_tree.yaml
index d60d5a8..39fccd6 100644
--- a/diskimage_builder/block_device/tests/config/multiple_partitions_tree.yaml
+++ b/diskimage_builder/block_device/tests/config/multiple_partitions_tree.yaml
@@ -2,39 +2,48 @@
name: image0
- partitioning:
- base: image0
- name: mbr
- label: mbr
- partitions:
- - name: root
- flags: [ boot, primary ]
- size: 55%
- mkfs:
- type: xfs
- uuid: root-uuid-1234
- mount:
- mount_point: /
- fstab:
- options: "defaults"
- fsck-passno: 1
- - name: var
- size: 40%
- mkfs:
- type: xfs
- uuid: var-uuid-1234
- mount:
- mount_point: /var
- fstab:
- options: "defaults"
- fsck-passno: 1
- - name: var_log
- size: 5%
- mkfs:
- type: vfat
- label: varlog
- mount:
- mount_point: /var/log
- fstab:
- options: "defaults"
- fsck-passno: 1
-
+ base: image0
+ name: mbr
+ label: mbr
+ partitions:
+ - name: root
+ flags: [boot, primary]
+ size: 54%
+ mkfs:
+ type: xfs
+ uuid: root-uuid-1234
+ mount:
+ mount_point: /
+ fstab:
+ options: "defaults"
+ fsck-passno: 1
+ - name: var
+ size: 40%
+ mkfs:
+ type: xfs
+ uuid: var-uuid-1234
+ mount:
+ mount_point: /var
+ fstab:
+ options: "defaults"
+ fsck-passno: 1
+ - name: var_log
+ size: 5%
+ mkfs:
+ type: vfat
+ label: varlog
+ mount:
+ mount_point: /var/log
+ fstab:
+ options: "defaults"
+ fsck-passno: 1
+ - name: swap
+ size: 1%
+ mkfs:
+ type: swap
+ uuid: swap-uuid-1234
+ mount:
+ mount_point: none
+ fstab:
+ fsck-passno: 0
+ options: "sw"
diff --git a/diskimage_builder/block_device/tests/test_mount_order.py b/diskimage_builder/block_device/tests/test_mount_order.py
index 097ae7d..06d34e4 100644
--- a/diskimage_builder/block_device/tests/test_mount_order.py
+++ b/diskimage_builder/block_device/tests/test_mount_order.py
@@ -80,6 +80,7 @@ class TestMountOrder(tc.TestGraphGeneration):
state['blockdev']['root'] = {'device': '/dev/loopXp1/root'}
state['blockdev']['var'] = {'device': '/dev/loopXp2/var'}
state['blockdev']['var_log'] = {'device': '/dev/loopXp3/var_log'}
+ state['blockdev']['swap'] = {'device': '/dev/loopXp4/swap'}
for node in call_order:
if isinstance(node, (FilesystemNode, MountPointNode)):
@@ -89,7 +90,8 @@ class TestMountOrder(tc.TestGraphGeneration):
node.umount()
# ensure that partitions were mounted in order root->var->var/log
- self.assertListEqual(state['mount_order'], ['/', '/var', '/var/log'])
+ self.assertListEqual(state['mount_order'],
+ ['/', '/var', '/var/log', 'none'])
# fs creation sequence (note we don't care about order of this
# as they're all independent)
@@ -101,7 +103,9 @@ class TestMountOrder(tc.TestGraphGeneration):
'-m', 'uuid=var-uuid-1234',
'-q', '/dev/loopXp2/var']),
mock.call(['mkfs', '-t', 'vfat', '-n', 'VARLOG',
- '/dev/loopXp3/var_log'])
+ '/dev/loopXp3/var_log']),
+ mock.call(['mkswap', '-L', 'mkfs_swap', '-U', 'swap-uuid-1234',
+ '/dev/loopXp4/swap'])
]
self.assertEqual(mock_exec_sudo_mkfs.call_count, len(cmd_sequence))
mock_exec_sudo_mkfs.assert_has_calls(cmd_sequence, any_order=True)
@@ -154,6 +158,10 @@ class TestMountOrder(tc.TestGraphGeneration):
'device': '/dev/loopXp3',
'fstype': 'vfat',
},
+ 'mkfs_swap': {
+ 'device': '/dev/loopXp4',
+ 'fstype': 'swap',
+ },
}
for node in call_order:
@@ -164,7 +172,9 @@ class TestMountOrder(tc.TestGraphGeneration):
node.umount()
# ensure that partitions are mounted in order / -> /boot -> /var
- self.assertListEqual(state['mount_order'], ['/', '/boot', '/var'])
+ # swap not mounted in runtime, but should be in 'mount_order' list
+ self.assertListEqual(state['mount_order'],
+ ['/', '/boot', '/var', 'none'])
cmd_sequence = [
# mount sequence
diff --git a/diskimage_builder/diskimage_builder.py b/diskimage_builder/diskimage_builder.py
new file mode 100644
index 0000000..3872b0c
--- /dev/null
+++ b/diskimage_builder/diskimage_builder.py
@@ -0,0 +1,574 @@
+# Copyright 2023 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import argparse
+import collections
+import io
+import jsonschema
+import os
+import os.path
+import shlex
+import subprocess
+import sys
+import textwrap
+import yaml
+
+import diskimage_builder.paths
+
+
+class SchemaProperty(object):
+ """Base class for a basic schema and a help string"""
+
+ key = None
+ description = None
+ schema_type = "string"
+
+ def __init__(self, key, description, schema_type=None):
+ self.key = key
+ self.description = description
+ if schema_type:
+ self.schema_type = schema_type
+
+ def to_schema(self):
+ return {self.key: {"type": self.schema_type}}
+
+ def type_help(self):
+ return "Value is a string"
+
+ def to_help(self):
+ return "%s\n%s\n%s\n(%s)" % (
+ self.key,
+ "-" * len(self.key),
+ "\n".join(textwrap.wrap(self.description)),
+ self.type_help(),
+ )
+
+
+class Env(SchemaProperty):
+ """String dict schema for environment variables"""
+
+ def __init__(self, key, description):
+ super(Env, self).__init__(key, description, schema_type="object")
+
+ def to_schema(self):
+ schema = super(Env, self).to_schema()
+ schema[self.key]["additionalProperties"] = {"type": "string"}
+ return schema
+
+ def type_help(self):
+ return "Value is a map of strings"
+
+
+class Arg(SchemaProperty):
+ """Command argument with associated value"""
+
+ arg = None
+
+ def __init__(self, key, description, schema_type=None, arg=None):
+ super(Arg, self).__init__(key, description, schema_type=schema_type)
+ self.arg = arg
+
+ def arg_name(self):
+ if self.arg is None:
+ return "--%s" % self.key
+ return self.arg
+
+ def to_argument(self, value=None):
+ arg = self.arg_name()
+ if value is not None and value != "":
+ return [arg, value]
+ return []
+
+
+class Flag(Arg):
+ """Boolean value which does not contribute to arguments"""
+
+ def __init__(self, key, description):
+ super(Flag, self).__init__(key, description, schema_type="boolean")
+
+ def to_argument(self, value=None):
+ return []
+
+ def type_help(self):
+ return "Value is a boolean"
+
+
+class ArgFlag(Arg):
+ """Boolean value for a flag argument being set or not"""
+
+ def __init__(self, key, description, arg=None):
+ super(ArgFlag, self).__init__(
+ key, description, arg=arg, schema_type="boolean"
+ )
+
+ def to_argument(self, value=None):
+ if value:
+ return [self.arg_name()]
+ return []
+
+ def type_help(self):
+ return "Value is a boolean"
+
+
+class ArgEnum(Arg):
+ """String argument constrained to a list of allowed values"""
+
+ enum = None
+
+ def __init__(
+ self, key, description, schema_type="string", arg=None, enum=None
+ ):
+ super(ArgEnum, self).__init__(
+ key, description, schema_type=schema_type, arg=arg
+ )
+ self.enum = enum and enum or []
+
+ def to_schema(self):
+ schema = super(ArgEnum, self).to_schema()
+ schema[self.key]["enum"] = self.enum
+ return schema
+
+ def type_help(self):
+ return "Allowed values: %s" % ", ".join(self.enum)
+
+
+class ArgFlagRepeating(ArgEnum):
+ """Flag argument which repeats the specified number of times"""
+
+ def __init__(self, key, description, arg=None, max_repeat=0):
+ enum = list(range(max_repeat + 1))
+ super(ArgFlagRepeating, self).__init__(
+ key, description, schema_type="integer", arg=arg, enum=enum
+ )
+
+ def to_argument(self, value):
+ return [self.arg] * value
+
+ def type_help(self):
+ return "Allowed values: %s" % ", ".join([str(i) for i in self.enum])
+
+
+class ArgInt(Arg):
+ """Integer argument which a minumum constraint"""
+
+ minimum = 1
+
+ def __init__(self, key, description, arg=None, minimum=1):
+ super(ArgInt, self).__init__(
+ key, description, arg=arg, schema_type="integer"
+ )
+ self.minimum = minimum
+
+ def to_schema(self):
+ schema = super(ArgInt, self).to_schema()
+ schema[self.key]["minimum"] = self.minimum
+ return schema
+
+ def to_argument(self, value):
+ return super(ArgInt, self).to_argument(str(value))
+
+ def type_help(self):
+ return "Value is an integer"
+
+
+class ArgList(Arg):
+ """List of strings converted to comma delimited argument"""
+
+ def __init__(self, key, description, arg=None):
+ super(ArgList, self).__init__(
+ key, description, arg=arg, schema_type="array"
+ )
+
+ def to_schema(self):
+ schema = super(ArgList, self).to_schema()
+ schema[self.key]["items"] = {"type": "string"}
+ return schema
+
+ def to_argument(self, value):
+ if not value:
+ return []
+ return super(ArgList, self).to_argument(",".join(value))
+
+ def type_help(self):
+ return "Value is a list of strings"
+
+
+class ArgListPositional(ArgList):
+ """List of strings converted to positional arguments"""
+
+ def __init__(self, key, description):
+ super(ArgListPositional, self).__init__(key, description)
+
+ def to_argument(self, value):
+ # it is already a list, just return it
+ return value
+
+ def type_help(self):
+ return "Value is a list of strings"
+
+
+class ArgEnumList(ArgList):
+ """List of strings constrained to a list of allowed values"""
+
+ enum = None
+
+ def __init__(self, key, description, arg=None, enum=None):
+ super(ArgEnumList, self).__init__(key, description, arg=arg)
+ self.enum = enum and enum or []
+
+ def to_schema(self):
+ schema = super(ArgEnumList, self).to_schema()
+ schema[self.key]["items"]["enum"] = self.enum
+ return schema
+
+ def type_help(self):
+ return (
+ "Value is a list of strings with allowed values: %s)"
+ % ", ".join(self.enum)
+ )
+
+
+class ArgDictToString(Arg):
+ """Dict with string values converted to key=value,key2=value2 argument"""
+
+ def __init__(self, key, description, arg=None):
+ super(ArgDictToString, self).__init__(
+ key, description, arg=arg, schema_type="object"
+ )
+
+ def to_schema(self):
+ schema = super(ArgDictToString, self).to_schema()
+ schema[self.key]["additionalProperties"] = {"type": "string"}
+ return schema
+
+ def to_argument(self, value):
+ as_list = []
+ for k, v in value.items():
+ as_list.append("%s=%s" % (k, v))
+ return super(ArgDictToString, self).to_argument(",".join(as_list))
+
+ def type_help(self):
+ return "Value is a map of strings"
+
+
+PROPERTIES = [
+ Arg("imagename", "Set the imagename of the output image file.", arg="-o"),
+ ArgEnum(
+ "arch",
+ "Set the architecture of the image.",
+ arg="-a",
+ enum=[
+ "aarch64",
+ "amd64",
+ "arm64",
+ "armhf",
+ "powerpc",
+ "ppc64",
+ "ppc64el",
+ "ppc64le",
+ "s390x",
+ "x86_64",
+ ],
+ ),
+ ArgEnumList(
+ "types",
+ "Set the image types of the output image files.",
+ arg="-t",
+ enum=[
+ "qcow2",
+ "tar",
+ "tgz",
+ "squashfs",
+ "vhd",
+ "docker",
+ "aci",
+ "raw",
+ ],
+ ),
+ Env(
+ "environment",
+ "Environment variables to set during the image build.",
+ ),
+ Flag(
+ "ramdisk",
+ "Whether to build a ramdisk image.",
+ ),
+ ArgFlagRepeating(
+ "debug-trace",
+ "Tracing level to log, integer 0 is off.",
+ arg="-x",
+ max_repeat=2,
+ ),
+ ArgFlag(
+ "uncompressed",
+ "Do not compress the image - larger but faster.",
+ arg="-u",
+ ),
+ ArgFlag("clear", "Clear environment before starting work.", arg="-c"),
+ Arg(
+ "logfile",
+ "Save run output to given logfile.",
+ ),
+ ArgFlag(
+ "checksum",
+ "Generate MD5 and SHA256 checksum files for the created image.",
+ ),
+ ArgInt(
+ "image-size",
+ "Image size in GB for the created image.",
+ ),
+ ArgInt(
+ "image-extra-size",
+ "Extra image size in GB for the created image.",
+ ),
+ Arg(
+ "image-cache",
+ "Location for cached images, defaults to ~/.cache/image-create.",
+ ),
+ ArgInt(
+ "max-online-resize",
+ "Max number of filesystem blocks to support when resizing. "
+ "Useful if you want a really large root partition when the "
+ "image is deployed. Using a very large value may run into a "
+ "known bug in resize2fs. Setting the value to 274877906944 "
+ "will get you a 1PB root file system. Making this "
+ "value unnecessarily large will consume extra disk "
+ "space on the root partition with extra file system inodes.",
+ ),
+ ArgInt(
+ "min-tmpfs",
+ "Minimum size in GB needed in tmpfs to build the image.",
+ ),
+ ArgInt(
+ "mkfs-journal-size",
+ "Filesystem journal size in MB to pass to mkfs.",
+ ),
+ Arg(
+ "mkfs-options",
+ "Option flags to be passed directly to mkfs.",
+ ),
+ ArgFlag("no-tmpfs", "Do not use tmpfs to speed image build."),
+ ArgFlag("offline", "Do not update cached resources."),
+ ArgDictToString(
+ "qemu-img-options",
+ "Option flags to be passed directly to qemu-img.",
+ ),
+ Arg(
+ "root-label",
+ 'Label for the root filesystem, defaults to "cloudimg-rootfs".',
+ ),
+ Arg(
+ "ramdisk-element",
+ "Specify the main element to be used for building ramdisks. "
+ 'Defaults to "ramdisk". Should be set to "dracut-ramdisk" '
+ "for platforms such as RHEL and CentOS that do not package busybox.",
+ ),
+ ArgEnum(
+ "install-type",
+ "Specify the default installation type.",
+ enum=["source", "package"],
+ ),
+ Arg(
+ "docker-target",
+ "Specify the repo and tag to use if the output type is docker, "
+ "defaults to the value of output imagename.",
+ ),
+ ArgList(
+ "packages",
+ "Extra packages to install in the image. Runs once, after "
+ '"install.d" phase. Does not apply when ramdisk is true.',
+ arg="-p",
+ ),
+ ArgFlag(
+ "skip-base",
+ 'Skip the default inclusion of the "base" element. '
+ "Does not apply when ramdisk is true.",
+ arg="-n",
+ ),
+ ArgListPositional(
+ "elements",
+ "list of elements to build the image with",
+ ),
+]
+
+
+SCHEMA_PROPERTIES = {}
+for arg in PROPERTIES:
+ SCHEMA_PROPERTIES.update(arg.to_schema())
+
+DIB_SCHEMA = {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": SCHEMA_PROPERTIES,
+ "additionalProperties": False,
+ },
+ "additionalProperties": False,
+}
+
+
+class Command(object):
+ script = None
+ args = None
+ environ = None
+
+ def __init__(self, script, properties, entry):
+ self.script = script
+ self.args = []
+ self.environ = {}
+ for prop in properties:
+ if prop.key in entry:
+ value = entry[prop.key]
+ if isinstance(prop, Env):
+ self.environ.update(value)
+ elif isinstance(prop, Arg):
+ self.args.extend(prop.to_argument(value))
+
+ def merged_env(self):
+ environ = os.environ.copy()
+ # pre-seed some paths for the shell script
+ environ["_LIB"] = diskimage_builder.paths.get_path("lib")
+ environ.update(self.environ)
+ return environ
+
+ def command(self):
+ return ["bash", self.script] + self.args
+
+ def __repr__(self):
+ elements = []
+ for k, v in self.environ.items():
+ elements.append("%s=%s" % (k, shlex.quote(v)))
+ elements.extend([shlex.quote(a) for a in self.command()])
+ return " ".join(elements) + "\n"
+
+
+def help_properties():
+ str = io.StringIO()
+ for prop in PROPERTIES:
+ str.write(prop.to_help())
+ str.write("\n\n")
+ return str.getvalue()
+
+
+def get_args():
+ description = (
+ """\
+The file format is YAML which expects a list of image definition maps.
+
+Supported entries for an image definition are:
+
+%s
+"""
+ % help_properties()
+ )
+ parser = argparse.ArgumentParser(
+ description=description,
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ )
+ parser.add_argument(
+ "files",
+ metavar="<filename>",
+ nargs="+",
+ help="Paths to image build definition YAML files",
+ )
+ parser.add_argument(
+ "--dry-run",
+ action="store_true",
+ help="Show the disk-image-create, ramdisk-image-create commands and "
+ "exit",
+ )
+ parser.add_argument(
+ "--stop-on-failure",
+ action="store_true",
+ help="Stop building images when an image build fails",
+ )
+ args = parser.parse_args(sys.argv[1:])
+ return args
+
+
+def merge_entry(merged_entry, entry):
+ for k, v in entry.items():
+ if isinstance(v, list):
+ # append to existing list
+ list_value = merged_entry.setdefault(k, [])
+ list_value.extend(v)
+ elif isinstance(v, dict):
+ # update environment dict
+ dict_value = merged_entry.setdefault(k, {})
+ dict_value.update(v)
+ else:
+ # update value
+ merged_entry[k] = v
+
+
+def build_commands(definition):
+ jsonschema.validate(definition, schema=DIB_SCHEMA)
+ dib_script = "%s/disk-image-create" % diskimage_builder.paths.get_path(
+ "lib"
+ )
+ rib_script = "%s/ramdisk-image-create" % diskimage_builder.paths.get_path(
+ "lib"
+ )
+
+ # Start with the default image name, 'image'
+ previous_imagename = "image"
+ merged_entries = collections.OrderedDict()
+ for entry in definition:
+ imagename = entry.get("imagename", previous_imagename)
+ previous_imagename = imagename
+ if imagename not in merged_entries:
+ merged_entries[imagename] = entry
+ else:
+ merge_entry(merged_entries[imagename], entry)
+
+ commands = []
+ for entry in merged_entries.values():
+ if entry.get("ramdisk", False):
+ commands.append(Command(rib_script, PROPERTIES, entry))
+ else:
+ commands.append(Command(dib_script, PROPERTIES, entry))
+ return commands
+
+
+def main():
+ args = get_args()
+
+ # export the path to the current python
+ if not os.environ.get("DIB_PYTHON_EXEC"):
+ os.environ["DIB_PYTHON_EXEC"] = sys.executable
+
+ definitions = []
+ for file in args.files:
+ with open(file) as f:
+ definitions.extend(yaml.safe_load(f))
+ commands = build_commands(definitions)
+ final_returncode = 0
+ failed_command = None
+ for command in commands:
+ sys.stderr.write(str(command))
+ sys.stderr.write("\n")
+ sys.stderr.flush()
+ if not args.dry_run:
+ p = subprocess.Popen(command.command(), env=command.merged_env())
+ p.communicate()
+ if p.returncode != 0:
+ final_returncode = p.returncode
+ failed_command = command
+ if args.stop_on_failure:
+ break
+
+ if final_returncode != 0:
+ raise subprocess.CalledProcessError(
+ final_returncode, failed_command.command()
+ )
diff --git a/diskimage_builder/elements/bootloader/finalise.d/50-bootloader b/diskimage_builder/elements/bootloader/finalise.d/50-bootloader
index 3e24332..64f0681 100755
--- a/diskimage_builder/elements/bootloader/finalise.d/50-bootloader
+++ b/diskimage_builder/elements/bootloader/finalise.d/50-bootloader
@@ -88,6 +88,52 @@ echo "GRUB_TIMEOUT=${DIB_GRUB_TIMEOUT:-5}" >>/etc/default/grub
echo 'GRUB_TERMINAL="serial console"' >>/etc/default/grub
echo 'GRUB_GFXPAYLOAD_LINUX=auto' >>/etc/default/grub
+# NOTE(TheJulia): We need to remove any boot entry from the /etc/default/grub
+# file that may already exist, such as what was added by fips being setup on
+# either in the source image or by by an element, as we repack the image.
+# with new filesystems.
+# Matches any element which looks like " boot=" and the associated value
+# in order for us to have a clean starting point to put a value in place,
+# if applicable.
+# Removes entry trailing with a space, or any entry where boot is set as
+# the last argument on the line.
+sed -i 's/\ boot=[0-9A-Za-z/=\-]\+//' /etc/default/grub
+# NOTE(TheJulia): When using FIPS, dracut wants to evaluate
+# the hmac files for the kernel checksum. However, if /boot is
+# located on a separate filesystem from the root filesystem,
+# than this fails. As a result, we need to identify IF /boot
+# is a separate filesystem, and convey this fact as a boot
+# argument so dracut does not halt the system on boot.
+
+if [[ -n "${DIB_BOOT_LABEL}" ]]; then
+ BOOT_FS="boot=LABEL=${DIB_BOOT_LABEL}"
+else
+ BOOT_FS=""
+fi
+
+# NOTE(TheJulia): While on the subject of FIPS, if there is not an
+# explicit /boot partition, then the fips setup command will return
+# a successful result, but then also tell you to update your grub
+# configuration. This happens specifically with Rocky linux.
+# as such, we check/reconcile the flag into place for the kernel
+# as the utility will return a result code of 1 if the state is
+# inconsistent, i.e. policy in place, but not kernel command line
+# argument.
+
+BOOT_FIPS=""
+
+if [[ -x /bin/fips-mode-setup ]]; then
+ set +e
+ fips-mode-setup --is-enabled
+ is_fips_enabled=$?
+ set -e
+ if [ $is_fips_enabled -eq 1 ]; then
+ BOOT_FIPS="fips=1"
+ fi
+fi
+
+
+
if [[ -n "${DIB_BOOTLOADER_SERIAL_CONSOLE}" ]]; then
SERIAL_CONSOLE="${DIB_BOOTLOADER_SERIAL_CONSOLE}"
elif [[ "powerpc ppc64 ppc64le" =~ "$ARCH" ]]; then
@@ -100,7 +146,7 @@ else
fi
GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=${SERIAL_CONSOLE} no_timer_check"
-echo "GRUB_CMDLINE_LINUX_DEFAULT=\"${GRUB_CMDLINE_LINUX_DEFAULT} ${DIB_BOOTLOADER_DEFAULT_CMDLINE}\"" >>/etc/default/grub
+echo "GRUB_CMDLINE_LINUX_DEFAULT=\"${GRUB_CMDLINE_LINUX_DEFAULT} ${DIB_BOOTLOADER_DEFAULT_CMDLINE} ${BOOT_FS} ${BOOT_FIPS}\"" >>/etc/default/grub
echo 'GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"' >>/etc/default/grub
# os-prober leaks /dev/sda into config file in dual-boot host
diff --git a/diskimage_builder/elements/cache-url/README.rst b/diskimage_builder/elements/cache-url/README.rst
index 5d30c9a..ec00c7e 100644
--- a/diskimage_builder/elements/cache-url/README.rst
+++ b/diskimage_builder/elements/cache-url/README.rst
@@ -1,4 +1,10 @@
=========
cache-url
=========
+
A helper script to download images into a local cache.
+
+**NOTE** : on RedHat platforms, ensure the curl binary is available.
+Due to conflicting differences in platform usage of ```curl-minimal``
+and ```curl``, the usual package dependency methods do not work for
+this package.
diff --git a/diskimage_builder/elements/cache-url/pkg-map b/diskimage_builder/elements/cache-url/pkg-map
index fa4fd95..bde555b 100644
--- a/diskimage_builder/elements/cache-url/pkg-map
+++ b/diskimage_builder/elements/cache-url/pkg-map
@@ -1,4 +1,9 @@
{
+ "family": {
+ "redhat": {
+ "curl": ""
+ }
+ },
"distro": {
"gentoo": {
"curl": "net-misc/curl"
diff --git a/diskimage_builder/elements/centos/pre-install.d/00-02-set-centos-mirror b/diskimage_builder/elements/centos/pre-install.d/00-02-set-centos-mirror
index cd02c37..ce97ecd 100755
--- a/diskimage_builder/elements/centos/pre-install.d/00-02-set-centos-mirror
+++ b/diskimage_builder/elements/centos/pre-install.d/00-02-set-centos-mirror
@@ -14,7 +14,11 @@ DIB_DISTRIBUTION_MIRROR=${DIB_DISTRIBUTION_MIRROR:-}
# The others aren't enabled and do not exist on all mirrors
if [[ ${DIB_RELEASE} == '7' ]]; then
sed -e "s,^#baseurl=http[s]*://mirror.centos.org/\(centos\|altarch\)/,baseurl=$DIB_DISTRIBUTION_MIRROR/,;/^mirrorlist=/d" -i /etc/yum.repos.d/CentOS-Base.repo
-# CentOS Stream releases (e.g. 8-stream, 9-stream)
+# CentOS Stream releases (9-stream)
+elif [[ ${DIB_RELEASE} =~ '9-stream' ]]; then
+ sed -e "s,^#baseurl=http[s]*://mirror.centos.org/\$contentdir/,baseurl=$DIB_DISTRIBUTION_MIRROR/,;/^mirrorlist=/d" -i /etc/yum.repos.d/centos.repo
+ sed -e "s,^#baseurl=http[s]*://mirror.centos.org/\$contentdir/,baseurl=$DIB_DISTRIBUTION_MIRROR/,;/^mirrorlist=/d" -i /etc/yum.repos.d/centos-addons.repo
+# CentOS Stream releases (8-stream)
elif [[ ${DIB_RELEASE} =~ '-stream' ]]; then
sed -e "s,^#baseurl=http[s]*://mirror.centos.org/\$contentdir/,baseurl=$DIB_DISTRIBUTION_MIRROR/,;/^mirrorlist=/d" -i /etc/yum.repos.d/CentOS-Stream-BaseOS.repo
sed -e "s,^#baseurl=http[s]*://mirror.centos.org/\$contentdir/,baseurl=$DIB_DISTRIBUTION_MIRROR/,;/^mirrorlist=/d" -i /etc/yum.repos.d/CentOS-Stream-AppStream.repo
diff --git a/diskimage_builder/elements/cloud-init-growpart/README.rst b/diskimage_builder/elements/cloud-init-growpart/README.rst
new file mode 100644
index 0000000..de07b61
--- /dev/null
+++ b/diskimage_builder/elements/cloud-init-growpart/README.rst
@@ -0,0 +1,22 @@
+===================
+cloud-init-growpart
+===================
+
+This element enables growpart for OS images. It allows to grow
+Specific partitions during the deployment process.
+To enable this element simply include it in the elements list.
+
+**Disclaimer:** This element might not work with some device names supplied, for example when server is deployed and the image is written to a fibre channel device, or a SAS/SATA SSD controller.
+
+* ``DIB_CLOUD_INIT_GROWPART_DEVICES``: List of partition names that needs to be populated in order to be grown by cloud-init. **Populating this variable is mandatory.**
+ Cloud-init growpart module documentation - https://cloudinit.readthedocs.io/en/latest/topics/modules.html?highlight=growpart#growpart::
+
+ DIB_CLOUD_INIT_GROWPART_DEVICES:
+ - /dev/sda1
+ - /dev/vda3
+
+
+Dependencies:
+
+* ``/usr/bin/growpart``: **is needed on the system in order to grow the partition**,
+ however it is part of different packages depending on linux family. That is already taken care of by package-installs.
diff --git a/diskimage_builder/elements/cloud-init-growpart/element-deps b/diskimage_builder/elements/cloud-init-growpart/element-deps
new file mode 100644
index 0000000..73015c2
--- /dev/null
+++ b/diskimage_builder/elements/cloud-init-growpart/element-deps
@@ -0,0 +1,2 @@
+package-installs
+pkg-map
diff --git a/diskimage_builder/elements/cloud-init-growpart/package-installs.yaml b/diskimage_builder/elements/cloud-init-growpart/package-installs.yaml
new file mode 100644
index 0000000..46a7087
--- /dev/null
+++ b/diskimage_builder/elements/cloud-init-growpart/package-installs.yaml
@@ -0,0 +1 @@
+growpart_package:
diff --git a/diskimage_builder/elements/cloud-init-growpart/pkg-map b/diskimage_builder/elements/cloud-init-growpart/pkg-map
new file mode 100644
index 0000000..4bfbc20
--- /dev/null
+++ b/diskimage_builder/elements/cloud-init-growpart/pkg-map
@@ -0,0 +1,10 @@
+{
+ "family": {
+ "redhat": {
+ "growpart_package": "cloud-utils-growpart"
+ },
+ "debian": {
+ "growpart_package": "cloud-guest-utils"
+ }
+ }
+}
diff --git a/diskimage_builder/elements/cloud-init-growpart/post-install.d/55-growpart b/diskimage_builder/elements/cloud-init-growpart/post-install.d/55-growpart
new file mode 100755
index 0000000..0f433b6
--- /dev/null
+++ b/diskimage_builder/elements/cloud-init-growpart/post-install.d/55-growpart
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+if [ ${DIB_DEBUG_TRACE:-1} -gt 0 ]; then
+ set -x
+fi
+set -eu
+set -o pipefail
+
+if [[ -n ${DIB_CLOUD_INIT_GROWPART_DEVICES} ]]; then
+ if [ -d /etc/cloud/cloud.cfg.d ]; then
+ cat > /etc/cloud/cloud.cfg.d/55-growpart.cfg <<EOF
+#cloud-config
+growpart:
+ mode: auto
+ devices: $DIB_CLOUD_INIT_GROWPART_DEVICES
+ ignore_growroot_disabled: false
+EOF
+ else
+ echo "The /etc/cloud/cloud.cfg.d directory must exist."
+ exit 1
+ fi
+else
+ echo "Set the device list in DIB_CLOUD_INIT_GROWPART_DEVICES."
+ exit 1
+fi
diff --git a/diskimage_builder/elements/cloud-init-growpart/releasenotes/notes/added_growpart_for_lvm-0ce76ba71710c720.yaml b/diskimage_builder/elements/cloud-init-growpart/releasenotes/notes/added_growpart_for_lvm-0ce76ba71710c720.yaml
new file mode 100644
index 0000000..fed8feb
--- /dev/null
+++ b/diskimage_builder/elements/cloud-init-growpart/releasenotes/notes/added_growpart_for_lvm-0ce76ba71710c720.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ Added growpart element. It allows for growing specific partitions
+ during the deployment, which will result in less post deploy actions
+ needed for the server to be ready for use.
+ \ No newline at end of file
diff --git a/diskimage_builder/elements/containerfile/root.d/08-containerfile b/diskimage_builder/elements/containerfile/root.d/08-containerfile
index 7a852ad..d8ac828 100755
--- a/diskimage_builder/elements/containerfile/root.d/08-containerfile
+++ b/diskimage_builder/elements/containerfile/root.d/08-containerfile
@@ -28,8 +28,13 @@ if [[ "${DIB_CONTAINERFILE_PODMAN_ROOT:-0}" != '0' ]]; then
DIB_CONTAINERFILE_RUNTIME_ROOT=1
fi
+# NOTE(ianw) 2022-12-15 : this used to be left blank, but we've found
+# with current podman this is the only reliable way to get networking
+# in the container we're building (needed for yum update, package
+# install, etc.). It's less secure, but we're already running in a
+# priviledged container ...
if [[ -z "${DIB_CONTAINERFILE_NETWORK_DRIVER:-}" ]]; then
- DIB_CONTAINERFILE_RUNTIME_NETWORK=""
+ DIB_CONTAINERFILE_RUNTIME_NETWORK="--network host"
else
DIB_CONTAINERFILE_RUNTIME_NETWORK="--network ${DIB_CONTAINERFILE_NETWORK_DRIVER:-}"
fi
diff --git a/diskimage_builder/elements/fedora-container/containerfiles/37 b/diskimage_builder/elements/fedora-container/containerfiles/37
new file mode 100644
index 0000000..550d2b9
--- /dev/null
+++ b/diskimage_builder/elements/fedora-container/containerfiles/37
@@ -0,0 +1,3 @@
+FROM docker.io/library/fedora:37
+
+RUN dnf install -y findutils util-linux
diff --git a/diskimage_builder/elements/fedora/environment.d/10-fedora-distro-name.bash b/diskimage_builder/elements/fedora/environment.d/10-fedora-distro-name.bash
index 78f0337..bb138d5 100644
--- a/diskimage_builder/elements/fedora/environment.d/10-fedora-distro-name.bash
+++ b/diskimage_builder/elements/fedora/environment.d/10-fedora-distro-name.bash
@@ -1,4 +1,4 @@
export DISTRO_NAME=fedora
-export DIB_RELEASE=${DIB_RELEASE:-36}
+export DIB_RELEASE=${DIB_RELEASE:-37}
export EFI_BOOT_DIR="EFI/fedora"
diff --git a/diskimage_builder/elements/fedora/root.d/10-fedora-cloud-image b/diskimage_builder/elements/fedora/root.d/10-fedora-cloud-image
index f3eb7bb..4cf69b6 100755
--- a/diskimage_builder/elements/fedora/root.d/10-fedora-cloud-image
+++ b/diskimage_builder/elements/fedora/root.d/10-fedora-cloud-image
@@ -12,6 +12,9 @@ set -o pipefail
if [ 'amd64' = "$ARCH" ] ; then
ARCH="x86_64"
fi
+if [[ "${ARCH}" == "arm64" ]]; then
+ ARCH="aarch64"
+fi
DIB_LOCAL_IMAGE=${DIB_LOCAL_IMAGE:-""}
diff --git a/diskimage_builder/elements/fips/README.rst b/diskimage_builder/elements/fips/README.rst
new file mode 100644
index 0000000..14a0a13
--- /dev/null
+++ b/diskimage_builder/elements/fips/README.rst
@@ -0,0 +1,24 @@
+====
+fips
+====
+
+This image element attempts to setup the image so it will boot and operate
+in what is often referred to as "FIPS mode", where cryptography policies
+and algorithms are enforced to only those which are FIPS approved and
+certified. In this context, FIPS is an abbreviation for
+Federal Information Processing Standard, specifically publication number
+140. You can learn more about FIPS policies at
+https://csrc.nist.gov/publications/fips
+
+This element is a best-effort element and additional software or elements
+may be processed after the fact which may impact the work of this element.
+It is **generally** regarded as critical to enable FIPS as early as possible,
+as cryptography policy can be applied, but may not be fully enforced without
+the kernel also operating in FIPS mode.
+
+If you intend to utilize this element to generate production FIPS images,
+it is highly recommended you do so on a host which has already had FIPS
+enabled for itself.
+
+Additionally, not all distributions are explicitly supported. Unsupported
+distributions will error providing appropriate guidance, if available.
diff --git a/diskimage_builder/elements/fips/package-installs.yaml b/diskimage_builder/elements/fips/package-installs.yaml
new file mode 100644
index 0000000..b22545c
--- /dev/null
+++ b/diskimage_builder/elements/fips/package-installs.yaml
@@ -0,0 +1,14 @@
+crypto-policies:
+ when:
+ - DISTRO_NAME != ubuntu
+ - DISTRO_NAME != gentoo
+# NOTE(TheJulia): crypto-policies does not exist in:
+# - ubuntu
+# - gentoo
+crypto-policies-scripts:
+ when:
+ - DISTRO_NAME != debian
+ - DISTRO_NAME != ubuntu
+ - DISTRO_NAME != gentoo
+# NOTE(TheJulia): Crypto policies includes the
+# fips-mode-setup script in the debian package.
diff --git a/diskimage_builder/elements/fips/pre-install.d/01-setup-fips b/diskimage_builder/elements/fips/pre-install.d/01-setup-fips
new file mode 100755
index 0000000..5d10318
--- /dev/null
+++ b/diskimage_builder/elements/fips/pre-install.d/01-setup-fips
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+if [ ${DIB_DEBUG_TRACE:-0} -gt 0 ]; then
+ set -x
+fi
+set -eu
+set -o pipefail
+
+
+if [[ "${DISTRO_NAME}" == "ubuntu" ]]; then
+ echo "ERROR: Setup of FIPS mode with DIB is not supported with Ubuntu."
+ echo "Please see refer to Ubuntu documentation on how to configure "
+ echo "FIPS, as it requires an Ubuntu Advantage subscription."
+ echo "https://ubuntu.com/security/certifications/docs/fips-enablement"
+ exit 1
+elif [[ "${DISTRO_NAME}" == "gentoo" ]]; then
+ echo "ERROR: Setup of FIPS mode with DIB is not supported with Gentoo."
+ echo "Gentoo's documentation appears to largely omit references to"
+ echo "FIPS setup, and the supportability is unknown."
+ exit 1
+elif [[ "${DISTRO_NAME}" == "opensuse" ]]; then
+ echo "ERROR: Setup of FIPS mode with DIB is not supported with OpenSUSE."
+ echo "Please refer to SUSE documentation on how to perform these actions."
+ echo "https://www.suse.com/support/kb/doc/?id=000019432"
+ exit 1
+else
+ # This command exists in Centos, Fedora, Rocky, and Debian
+ # and is referenced in documentation and posts about how to setup FIPS.
+ echo "Attempting to setup FIPS mode utilizing the fips-mode-setup command."
+ fips-mode-setup --enable
+ echo "FIPS mode setup completed, please remember this only applies to a"
+ echo "running operating system nor implies the certification state of the"
+ echo "resulting running operating system."
+fi
diff --git a/diskimage_builder/elements/growvols/static/usr/local/sbin/growvols b/diskimage_builder/elements/growvols/static/usr/local/sbin/growvols
index 8c0249e..8894bed 100755
--- a/diskimage_builder/elements/growvols/static/usr/local/sbin/growvols
+++ b/diskimage_builder/elements/growvols/static/usr/local/sbin/growvols
@@ -36,12 +36,22 @@ UNITS = ['%']
UNITS.extend(UNIT_BYTES.keys())
AMOUNT_UNIT_RE = re.compile('^([0-9]+)(%s)$' % '|'.join(UNITS))
+UNIT_BYTES_FORMAT = {
+ 'B': 1,
+ 'KiB': 1024,
+ 'MiB': 1048576,
+ 'GiB': 1073741824
+}
+
# Only create growth partition if there is at least 1GiB available
MIN_DISK_SPACE_BYTES = UNIT_BYTES['GiB']
# Default LVM physical extent size is 4MiB
PHYSICAL_EXTENT_BYTES = 4 * UNIT_BYTES['MiB']
+# Grow the thin pool metadata size to 1GiB
+POOL_METADATA_SIZE = UNIT_BYTES['GiB']
+
class Command(object):
""" An object to represent a command to run with associated comment """
@@ -172,13 +182,13 @@ def printable_cmd(cmd):
def convert_bytes(num):
- """Format a bytes amount with units MB, GB etc"""
- step_unit = 1000.0
-
- for x in ['B', 'KB', 'MB', 'GB', 'TB']:
- if num < step_unit:
- return "%d%s" % (num, x)
- num /= step_unit
+ """Format a bytes amount with units GiB, MiB etc"""
+ for x in ['GiB', 'MiB', 'KiB', 'B']:
+ unit = UNIT_BYTES_FORMAT[x]
+ unit_num = num // unit
+ if unit_num > 0:
+ break
+ return "%d%s" % (unit_num, x)
def execute(cmd):
@@ -259,6 +269,17 @@ def find_disk(opts, devices):
return device
+def grow_gpt(disk_name):
+ device = '/dev/%s' % disk_name
+ output = execute(['sgdisk', '-v', device])
+
+ search_str = "it doesn't reside\nat the end of the disk"
+ if search_str in output:
+ LOG.info('Fixing GPT structure, moving to end of device %s', device)
+ execute(['sgdisk', '-e', device])
+ execute(['partprobe'])
+
+
def find_space(disk_name):
LOG.info('Finding spare space to grow into')
dev_path = '/dev/%s' % disk_name
@@ -480,6 +501,8 @@ def main(argv):
disk = find_disk(opts, devices)
disk_name = disk['KNAME']
+ grow_gpt(disk_name)
+
sector_bytes = find_sector_size(disk_name)
sector_start, sector_end, size_sectors = find_space(disk_name)
@@ -499,9 +522,16 @@ def main(argv):
group = find_group(opts)
partnum = find_next_partnum(devices, disk_name)
devname = find_next_device_name(devices, disk_name, partnum)
+ thin_pool = find_thin_pool(devices, group)
+ if thin_pool:
+ # total size available, reduced by POOL_METADATA_SIZE
+ # rounded down to whole extent and reduced by 1 extent
+ # for metadata overhead
+ size_bytes -= POOL_METADATA_SIZE
+ size_bytes -= size_bytes % PHYSICAL_EXTENT_BYTES
+ size_bytes -= PHYSICAL_EXTENT_BYTES
dev_path = '/dev/%s' % devname
grow_vols = find_grow_vols(opts, devices, group, size_bytes)
- thin_pool = find_thin_pool(devices, group)
commands = []
@@ -528,14 +558,20 @@ def main(argv):
], 'Add physical volume %s to group %s' % (devname, group)))
if thin_pool:
- # total size available, rounded down to whole extents
- pool_size = size_bytes - size_bytes % PHYSICAL_EXTENT_BYTES
commands.append(Command([
'lvextend',
- '-L+%sB' % pool_size,
+ '--poolmetadatasize',
+ '+%sB' % POOL_METADATA_SIZE,
+ thin_pool,
+ dev_path
+ ], 'Add %s to thin pool metadata %s' % (
+ convert_bytes(POOL_METADATA_SIZE), thin_pool)))
+ commands.append(Command([
+ 'lvextend',
+ '-L+%sB' % size_bytes,
thin_pool,
dev_path
- ], 'Add %s to thin pool %s' % (convert_bytes(pool_size),
+ ], 'Add %s to thin pool %s' % (convert_bytes(size_bytes),
thin_pool)))
for volume_path, size_bytes in grow_vols.items():
diff --git a/diskimage_builder/elements/growvols/tests/test_growvols.py b/diskimage_builder/elements/growvols/tests/test_growvols.py
index 7c2deb9..e45c652 100644
--- a/diskimage_builder/elements/growvols/tests/test_growvols.py
+++ b/diskimage_builder/elements/growvols/tests/test_growvols.py
@@ -110,6 +110,13 @@ DEVICES = [{
SECTOR_START = 79267840
SECTOR_END = 488265727
SGDISK_LARGEST = "%s\n%s\n" % (SECTOR_START, SECTOR_END)
+SGDISK_V = """
+Problem: The secondary header's self-pointer indicates that it doesn't reside
+at the end of the disk. If you've added a disk to a RAID array, use the 'e'
+option on the experts' menu to adjust the secondary header's and partition
+table's locations.
+
+Identified 1 problems!"""
# output of vgs --noheadings --options vg_name
VGS = " vg\n"
@@ -147,10 +154,10 @@ class TestGrowvols(base.BaseTestCase):
def test_convert_bytes(self):
self.assertEqual('100B', growvols.convert_bytes(100))
- self.assertEqual('1KB', growvols.convert_bytes(1000))
- self.assertEqual('2MB', growvols.convert_bytes(2000000))
- self.assertEqual('3GB', growvols.convert_bytes(3000000000))
- self.assertEqual('4TB', growvols.convert_bytes(4000000000000))
+ self.assertEqual('1000B', growvols.convert_bytes(1000))
+ self.assertEqual('1MiB', growvols.convert_bytes(2000000))
+ self.assertEqual('2GiB', growvols.convert_bytes(3000000000))
+ self.assertEqual('3725GiB', growvols.convert_bytes(4000000000000))
@mock.patch('subprocess.Popen')
def test_execute(self, mock_popen):
@@ -465,6 +472,9 @@ class TestGrowvols(base.BaseTestCase):
# noop, only discover block device info
mock_execute.side_effect = [
LSBLK,
+ SGDISK_V,
+ '',
+ '',
SGDISK_LARGEST,
VGS,
LVS,
@@ -473,6 +483,9 @@ class TestGrowvols(base.BaseTestCase):
mock_execute.assert_has_calls([
mock.call(['lsblk', '-Po',
'kname,pkname,name,label,type,fstype,mountpoint']),
+ mock.call(['sgdisk', '-v', '/dev/sda']),
+ mock.call(['sgdisk', '-e', '/dev/sda']),
+ mock.call(['partprobe']),
mock.call(['sgdisk', '--first-aligned-in-largest',
'--end-of-largest', '/dev/sda']),
mock.call(['vgs', '--noheadings', '--options', 'vg_name']),
@@ -484,6 +497,7 @@ class TestGrowvols(base.BaseTestCase):
mock_execute.reset_mock()
mock_execute.side_effect = [
LSBLK,
+ '',
SGDISK_LARGEST,
VGS,
LVS,
@@ -493,6 +507,7 @@ class TestGrowvols(base.BaseTestCase):
mock_execute.assert_has_calls([
mock.call(['lsblk', '-Po',
'kname,pkname,name,label,type,fstype,mountpoint']),
+ mock.call(['sgdisk', '-v', '/dev/sda']),
mock.call(['sgdisk', '--first-aligned-in-largest',
'--end-of-largest', '/dev/sda']),
mock.call(['vgs', '--noheadings', '--options', 'vg_name']),
@@ -512,6 +527,7 @@ class TestGrowvols(base.BaseTestCase):
mock_execute.reset_mock()
mock_execute.side_effect = [
LSBLK,
+ '',
SGDISK_LARGEST,
VGS,
LVS,
@@ -522,6 +538,7 @@ class TestGrowvols(base.BaseTestCase):
mock_execute.assert_has_calls([
mock.call(['lsblk', '-Po',
'kname,pkname,name,label,type,fstype,mountpoint']),
+ mock.call(['sgdisk', '-v', '/dev/sda']),
mock.call(['sgdisk', '--first-aligned-in-largest',
'--end-of-largest', '/dev/sda']),
mock.call(['vgs', '--noheadings', '--options', 'vg_name']),
@@ -549,6 +566,7 @@ class TestGrowvols(base.BaseTestCase):
sgdisk_largest = "%s\n%s\n" % (sector_start, sector_end)
mock_execute.side_effect = [
LSBLK,
+ '',
sgdisk_largest,
VGS,
LVS,
@@ -561,6 +579,7 @@ class TestGrowvols(base.BaseTestCase):
# no space to grow, success
mock_execute.side_effect = [
LSBLK,
+ '',
sgdisk_largest,
VGS,
LVS,
@@ -579,16 +598,18 @@ class TestGrowvols(base.BaseTestCase):
mock_execute.reset_mock()
mock_execute.side_effect = [
LSBLK,
+ '',
SGDISK_LARGEST,
VGS,
LVS_THIN,
- '', '', '', '', '', '', '', '', '', '', ''
+ '', '', '', '', '', '', '', '', '', '', '', ''
]
growvols.main(['growvols', '--yes', '--group', 'vg',
'/home=20%', 'fs_var=40%'])
mock_execute.assert_has_calls([
mock.call(['lsblk', '-Po',
'kname,pkname,name,label,type,fstype,mountpoint']),
+ mock.call(['sgdisk', '-v', '/dev/sda']),
mock.call(['sgdisk', '--first-aligned-in-largest',
'--end-of-largest', '/dev/sda']),
mock.call(['vgs', '--noheadings', '--options', 'vg_name']),
@@ -599,13 +620,15 @@ class TestGrowvols(base.BaseTestCase):
mock.call(['partprobe']),
mock.call(['pvcreate', '/dev/sda5']),
mock.call(['vgextend', 'vg', '/dev/sda5']),
- mock.call(['lvextend', '-L+209404821504B',
+ mock.call(['lvextend', '--poolmetadatasize', '+1073741824B',
'/dev/mapper/vg-lv_thinpool', '/dev/sda5']),
- mock.call(['lvextend', '--size', '+41880125440B',
+ mock.call(['lvextend', '-L+208326885376B',
+ '/dev/mapper/vg-lv_thinpool', '/dev/sda5']),
+ mock.call(['lvextend', '--size', '+41662021632B',
'/dev/mapper/vg-lv_home']),
- mock.call(['lvextend', '--size', '+83760250880B',
+ mock.call(['lvextend', '--size', '+83328237568B',
'/dev/mapper/vg-lv_var']),
- mock.call(['lvextend', '--size', '+83764445184B',
+ mock.call(['lvextend', '--size', '+83336626176B',
'/dev/mapper/vg-lv_root']),
mock.call(['xfs_growfs', '/dev/mapper/vg-lv_home']),
mock.call(['xfs_growfs', '/dev/mapper/vg-lv_var']),
diff --git a/diskimage_builder/elements/openeuler-minimal/pre-install.d/00-setup-mirror.bash b/diskimage_builder/elements/openeuler-minimal/pre-install.d/00-setup-mirror
index 312f034..339c896 100644..100755
--- a/diskimage_builder/elements/openeuler-minimal/pre-install.d/00-setup-mirror.bash
+++ b/diskimage_builder/elements/openeuler-minimal/pre-install.d/00-setup-mirror
@@ -1,3 +1,11 @@
+#!/bin/bash
+
+if [ ${DIB_DEBUG_TRACE:-0} -gt 0 ]; then
+ set -x
+fi
+set -eu
+set -o pipefail
+
if [ -n "${DIB_DISTRIBUTION_MIRROR:-}" ]; then
# Only set the mirror for OS, everything, EPOL and update repositories,
# The others (debuginfo and source) aren't mirrored since they do not exist on all mirrors
diff --git a/diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/README.rst b/diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/README.rst
new file mode 100644
index 0000000..10774f7
--- /dev/null
+++ b/diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/README.rst
@@ -0,0 +1 @@
+Verify a Rocky 9 aarch64 image
diff --git a/diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/element-deps b/diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/element-deps
new file mode 100644
index 0000000..99857b0
--- /dev/null
+++ b/diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/element-deps
@@ -0,0 +1,3 @@
+block-device-efi
+openstack-ci-mirrors
+vm
diff --git a/diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/environment.d/09-set-distro.bash b/diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/environment.d/09-set-distro.bash
new file mode 100644
index 0000000..65c6e4e
--- /dev/null
+++ b/diskimage_builder/elements/rocky-container/test-elements/rocky-9-aarch64-build-succeeds/environment.d/09-set-distro.bash
@@ -0,0 +1 @@
+export DIB_RELEASE='9'
diff --git a/diskimage_builder/elements/sysprep/bin/extract-image b/diskimage_builder/elements/sysprep/bin/extract-image
index c460dcc..cc4173e 100755
--- a/diskimage_builder/elements/sysprep/bin/extract-image
+++ b/diskimage_builder/elements/sysprep/bin/extract-image
@@ -97,9 +97,9 @@ function extract_image() {
fi
for LOOPDEV in ${LOOPDEVS}; do
- fstype=$(lsblk --all --nodeps --noheadings --output FSTYPE $LOOPDEV)
- label=$(lsblk --all --nodeps --noheadings --output LABEL $LOOPDEV)
- part_type=$(lsblk --all --nodeps --noheadings --output PARTTYPE $LOOPDEV)
+ fstype=$(sudo blkid -o value -s TYPE -p "${LOOPDEV}" 2>/dev/null)
+ label=$(sudo blkid -o value -s LABEL -p "${LOOPDEV}" 2>/dev/null)
+ part_type=$(sudo blkid -o value -s PART_ENTRY_TYPE -p "${LOOPDEV}" 2>/dev/null)
if [ -z "${fstype}" ]; then
# Ignore block device with no filesystem type
diff --git a/diskimage_builder/elements/ubuntu/post-install.d/99-autoremove b/diskimage_builder/elements/ubuntu-common/post-install.d/99-autoremove
index e04006d..e04006d 100755
--- a/diskimage_builder/elements/ubuntu/post-install.d/99-autoremove
+++ b/diskimage_builder/elements/ubuntu-common/post-install.d/99-autoremove
diff --git a/diskimage_builder/elements/yum-minimal/pkg-map b/diskimage_builder/elements/yum-minimal/pkg-map
index 45d8b27..edb0416 100644
--- a/diskimage_builder/elements/yum-minimal/pkg-map
+++ b/diskimage_builder/elements/yum-minimal/pkg-map
@@ -1,4 +1,15 @@
{
+ "release": {
+ "centos": {
+ "7": {
+ "NetworkManager": "",
+ "dhcp-client": ""
+ },
+ "9-stream": {
+ "lsb_release": "ed hostname patch postfix tar time"
+ }
+ }
+ },
"distro": {
"openeuler": {
"linux-firmware": "",
@@ -7,25 +18,9 @@
"redhat-rpm-config": "openEuler-rpm-config"
}
},
- "release": {
- "centos": {
- "7": {
- "NetworkManager": "",
- "dhcp-client": ""
- }
- }
- },
- "release": {
- "centos": {
- "9-stream": {
- "lsb_release": "ed hostname patch postfix tar time"
- }
- }
- },
-"family": {
+ "family": {
"redhat": {
"lsb_release": "redhat-lsb-core"
}
}
}
-
diff --git a/diskimage_builder/elements/yum/README.rst b/diskimage_builder/elements/yum/README.rst
index c4442ee..6ee06d4 100644
--- a/diskimage_builder/elements/yum/README.rst
+++ b/diskimage_builder/elements/yum/README.rst
@@ -22,20 +22,22 @@ The yum repository can also be configured by defining `DIB_YUM_REPO_PACKAGE` as
a yum available package or a URL to an rpm file. This package can install repo
files with any associated keys and certificates.
-Environment Variables for Module Selection during Image Creation
-----------------------------------------------------------------
-The following environment variable is used to select module streams to be
-enabled during an image build on Yum/DNF based distributions. Any existing
-stream for the given module is first disabled prior to enabling
-the specified stream.
-
-#### DIB\_DNF\_MODULE\_STREAMS
-This is a space-separated list of module streams to enable prior to any
-RPMs being installed.
-
-Image Build Module Selection Example
-------------------------------------
-When using Train release on RHEL/CentOS/Fedora, one must select the appropriate
-virt and container-tools module streams:
-
-DIB_DNF_MODULE_STREAMS='virt:8.2 container-tools:3.0'
+Environment Variables
+---------------------
+
+DIB_DNF_MODULE_STREAMS
+ :Required: No
+ :Default: None
+ :Description: The following environment variable is used to select module streams
+ to be enabled during an image build on Yum/DNF based distributions.Any existing
+ stream for the given module is first disabled prior to enabling the specified
+ stream.
+ :Example: ``DIB_DNF_MODULE_STREAMS='virt:8.2 container-tools:3.0'``
+
+DIB_CENTOS_7_PREINSTALL_EPEL_URL_PACKAGE
+ :Required: No
+ :Default: https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
+ :Description: The environment variable is used to override default value in pre-install
+ stage to install epel repository from custom source
+ :Example: ``DIB_CENTOS_7_PREINSTALL_EPEL_URL_PACKAGE=http://repos.example.com/epel/epel-latest-7.noarch.rpm``
+
diff --git a/diskimage_builder/elements/yum/pre-install.d/01-00-centos-python3 b/diskimage_builder/elements/yum/pre-install.d/01-00-centos-python3
index 58de4ce..d023353 100755
--- a/diskimage_builder/elements/yum/pre-install.d/01-00-centos-python3
+++ b/diskimage_builder/elements/yum/pre-install.d/01-00-centos-python3
@@ -17,7 +17,7 @@ if [[ ${DISTRO_NAME} =~ (centos|rhel) && ${DIB_RELEASE} == 7 ]]; then
# early stage.
yum install -y python3
# NOTE(dpawlik) The epel-release package is not available in RHEL.
- yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
+ yum install -y ${DIB_CENTOS_7_PREINSTALL_EPEL_URL_PACKAGE:-https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm}
yum install -y python36-PyYAML
yum remove -y epel-release
elif [[ ${DISTRO_NAME} =~ (centos|rhel) && ${DIB_RELEASE} > 7 ]]; then
diff --git a/diskimage_builder/lib/disk-image-create b/diskimage_builder/lib/disk-image-create
index d5a0396..a79686a 100644
--- a/diskimage_builder/lib/disk-image-create
+++ b/diskimage_builder/lib/disk-image-create
@@ -343,6 +343,11 @@ export DIB_ROOT_LABEL
DIB_ROOT_FSTYPE=$(${DIB_BLOCK_DEVICE} getval root-fstype)
export DIB_ROOT_FSTYPE
+# Need to get the boot device label because, if defined, we may
+# need to update boot configuration in some cases
+DIB_BOOT_LABEL=$(${DIB_BLOCK_DEVICE} getval boot-label)
+export DIB_BOOT_LABEL
+
# retrieve mount points so we can reuse in elements
DIB_MOUNTPOINTS=$(${DIB_BLOCK_DEVICE} getval mount-points)
export DIB_MOUNTPOINTS
diff --git a/diskimage_builder/lib/ramdisk-image-create b/diskimage_builder/lib/ramdisk-image-create
index d5a0396..a79686a 100644
--- a/diskimage_builder/lib/ramdisk-image-create
+++ b/diskimage_builder/lib/ramdisk-image-create
@@ -343,6 +343,11 @@ export DIB_ROOT_LABEL
DIB_ROOT_FSTYPE=$(${DIB_BLOCK_DEVICE} getval root-fstype)
export DIB_ROOT_FSTYPE
+# Need to get the boot device label because, if defined, we may
+# need to update boot configuration in some cases
+DIB_BOOT_LABEL=$(${DIB_BLOCK_DEVICE} getval boot-label)
+export DIB_BOOT_LABEL
+
# retrieve mount points so we can reuse in elements
DIB_MOUNTPOINTS=$(${DIB_BLOCK_DEVICE} getval mount-points)
export DIB_MOUNTPOINTS
diff --git a/diskimage_builder/tests/test_diskimage_builder.py b/diskimage_builder/tests/test_diskimage_builder.py
new file mode 100644
index 0000000..30b3b7d
--- /dev/null
+++ b/diskimage_builder/tests/test_diskimage_builder.py
@@ -0,0 +1,587 @@
+# Copyright 2023 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import jsonschema
+import mock
+import subprocess
+import tempfile
+import testtools
+import os
+import yaml
+
+from diskimage_builder import diskimage_builder as dib
+
+
+class TestDib(testtools.TestCase):
+ def assert_to_argument(self, expected, prop, value):
+ self.assertEqual(expected, prop.to_argument(value))
+ self.assert_schema_validate(prop, value)
+
+ def assert_schema_validate(self, prop, value, assert_failure=False):
+ # create a fake dict value and validate the schema against it
+ value_dict = {prop.key: value}
+ schema = {"type": "object", "properties": {}}
+ schema["properties"].update(prop.to_schema())
+ if assert_failure:
+ self.assertRaises(
+ jsonschema.exceptions.ValidationError,
+ jsonschema.validate,
+ value_dict,
+ schema=schema,
+ )
+ else:
+ jsonschema.validate(value_dict, schema=schema)
+
+ def test_schema_property(self):
+ x = dib.SchemaProperty(
+ "the_key", "the description", schema_type="integer"
+ )
+ self.assertEqual(
+ """\
+the_key
+-------
+the description
+(Value is a string)""",
+ x.to_help(),
+ )
+ self.assertEqual({"the_key": {"type": "integer"}}, x.to_schema())
+
+ def test_env(self):
+ x = dib.Env(
+ "environment",
+ "environment variables to set during the image build",
+ )
+ self.assertEqual(
+ {
+ "environment": {
+ "additionalProperties": {"type": "string"},
+ "type": "object",
+ }
+ },
+ x.to_schema(),
+ )
+
+ def test_arg(self):
+ # no arg
+ x = dib.Arg("the-key", "")
+ self.assert_to_argument(["--the-key", "the value"], x, "the value")
+
+ # with arg
+ x = dib.Arg("the-key", "", arg="--key")
+ self.assert_to_argument(["--key", "the value"], x, "the value")
+
+ # with empty string value
+ self.assert_to_argument([], x, "")
+
+ def test_arg_flag(self):
+ x = dib.ArgFlag("doit", "do it", arg="-d")
+ self.assertEqual({"doit": {"type": "boolean"}}, x.to_schema())
+
+ # false value
+ self.assert_to_argument([], x, False)
+
+ # true value
+ self.assert_to_argument(["-d"], x, True)
+
+ def test_arg_enum(self):
+ x = dib.ArgEnum("choice", "", enum=["one", "two", "three"])
+ self.assertEqual(
+ {"choice": {"type": "string", "enum": ["one", "two", "three"]}},
+ x.to_schema(),
+ )
+ self.assert_to_argument(["--choice", "one"], x, "one")
+ self.assert_schema_validate(x, "two")
+ self.assert_schema_validate(x, "four", assert_failure=True)
+
+ def test_arg_flag_repeating(self):
+ x = dib.ArgFlagRepeating("log_level", "", arg="-v", max_repeat=3)
+ self.assertEqual(
+ {"log_level": {"type": "integer", "enum": [0, 1, 2, 3]}},
+ x.to_schema(),
+ )
+ self.assert_to_argument([], x, 0)
+ self.assert_to_argument(["-v"], x, 1)
+ self.assert_to_argument(["-v", "-v"], x, 2)
+ self.assert_to_argument(["-v", "-v", "-v"], x, 3)
+
+ def test_arg_int(self):
+ x = dib.ArgInt("size", "")
+ self.assertEqual(
+ {"size": {"type": "integer", "minimum": 1}}, x.to_schema()
+ )
+ self.assert_to_argument(["--size", "10"], x, 10)
+ self.assert_schema_validate(x, -1, assert_failure=True)
+
+ def test_arg_list(self):
+ x = dib.ArgList("packages", "", arg="-p")
+ self.assertEqual(
+ {"packages": {"type": "array", "items": {"type": "string"}}},
+ x.to_schema(),
+ )
+ self.assert_to_argument(
+ ["-p", "wget,vim-enhanced"], x, ["wget", "vim-enhanced"]
+ )
+ self.assert_to_argument([], x, [])
+
+ def test_arg_list_position(self):
+ x = dib.ArgListPositional("elements", "")
+ self.assert_to_argument(
+ ["centos", "vm", "bootloader"], x, ["centos", "vm", "bootloader"]
+ )
+
+ def test_arg_enum_list(self):
+ x = dib.ArgEnumList(
+ "types", "", arg="-t", enum=["qcow2", "tar", "raw"]
+ )
+ self.assertEqual(
+ {
+ "types": {
+ "items": {
+ "enum": ["qcow2", "tar", "raw"],
+ "type": "string",
+ },
+ "type": "array",
+ }
+ },
+ x.to_schema(),
+ )
+ self.assert_to_argument(["-t", "qcow2,raw"], x, ["qcow2", "raw"])
+
+ def test_arg_dict_to_string(self):
+ x = dib.ArgDictToString("options", "")
+ self.assertEqual(
+ {
+ "options": {
+ "additionalProperties": {"type": "string"},
+ "type": "object",
+ }
+ },
+ x.to_schema(),
+ )
+ self.assert_to_argument(
+ ["--options", "foo=bar,baz=ingo"],
+ x,
+ {"foo": "bar", "baz": "ingo"},
+ )
+
+ def test_command_merged_env(self):
+ c = dib.Command(
+ "echo",
+ properties=[dib.Env("environment", "")],
+ entry={
+ "environment": {
+ "ELEMENTS_PATH": "/path/to/elements",
+ "DIB_CLOUD_IMAGES": "/path/to/image.qcow2",
+ }
+ },
+ )
+ env = c.merged_env()
+ self.assertEqual("/path/to/elements", env["ELEMENTS_PATH"])
+ self.assertEqual("/path/to/image.qcow2", env["DIB_CLOUD_IMAGES"])
+ self.assertIn(needle="_LIB", haystack=env)
+ # this will be merged with the whole environment, so there will be
+ # more than 3 values
+ self.assertGreater(len(env), 3)
+
+ def test_command(self):
+ c = dib.Command(
+ "echo",
+ properties=[
+ dib.Env("environment", ""),
+ dib.Arg("the-key", "", arg="--key"),
+ dib.ArgFlag("doit", "do it", arg="-d"),
+ dib.ArgFlagRepeating("verbose", "", arg="-v", max_repeat=3),
+ dib.ArgDictToString("options", ""),
+ dib.ArgListPositional("elements", ""),
+ ],
+ entry={
+ "environment": {
+ "ELEMENTS_PATH": "/path/to/elements",
+ "DIB_CLOUD_IMAGES": "~/image.qcow2",
+ },
+ "the-key": "the-value",
+ "doit": True,
+ "verbose": 3,
+ "options": {"foo": "bar"},
+ "elements": ["centos", "vm"],
+ },
+ )
+ self.assertEqual(
+ [
+ "bash",
+ "echo",
+ "--key",
+ "the-value",
+ "-d",
+ "-v",
+ "-v",
+ "-v",
+ "--options",
+ "foo=bar",
+ "centos",
+ "vm",
+ ],
+ c.command(),
+ )
+ self.assertEqual(
+ "ELEMENTS_PATH=/path/to/elements "
+ "DIB_CLOUD_IMAGES='~/image.qcow2' "
+ "bash echo --key the-value -d -v -v -v --options foo=bar "
+ "centos vm\n",
+ str(c),
+ )
+
+ def test_merge_entry(self):
+ # override normal attributes
+ merged_entry = {
+ "imagename": "image1",
+ "elements": ["one", "two", "three"],
+ "debug-trace": 1,
+ }
+ dib.merge_entry(
+ merged_entry,
+ {
+ "imagename": "image1",
+ "debug-trace": 2,
+ "logfile": "image1.log",
+ },
+ )
+ self.assertEqual(
+ {
+ "imagename": "image1",
+ "elements": ["one", "two", "three"],
+ "debug-trace": 2,
+ "logfile": "image1.log",
+ },
+ merged_entry,
+ )
+
+ # append list attributes, update dict attributes
+ merged_entry = {
+ "imagename": "image1",
+ "elements": ["one", "two", "three"],
+ "environment": {
+ "DIB_ONE": "1",
+ "DIB_TWO": "2",
+ },
+ }
+ dib.merge_entry(
+ merged_entry,
+ {
+ "imagename": "image1",
+ "elements": ["four", "five"],
+ "environment": {
+ "DIB_TWO": "two",
+ "DIB_THREE": "three",
+ },
+ },
+ )
+ self.assertEqual(
+ {
+ "imagename": "image1",
+ "elements": ["one", "two", "three", "four", "five"],
+ "environment": {
+ "DIB_ONE": "1",
+ "DIB_TWO": "two",
+ "DIB_THREE": "three",
+ },
+ },
+ merged_entry,
+ )
+
+ @mock.patch("diskimage_builder.paths.get_path")
+ def test_build_commands_simple(self, mock_get_path):
+ mock_get_path.return_value = "/lib"
+ commands = dib.build_commands(
+ [
+ {
+ "imagename": "centos-minimal",
+ "elements": ["centos", "vm"],
+ },
+ {
+ "imagename": "ironic-python-agent",
+ "ramdisk": True,
+ "elements": [
+ "ironic-python-agent-ramdisk",
+ "extra-hardware",
+ ],
+ },
+ ]
+ )
+
+ self.assertEqual(
+ [
+ "bash",
+ "/lib/disk-image-create",
+ "-o",
+ "centos-minimal",
+ "centos",
+ "vm",
+ ],
+ commands[0].command(),
+ )
+ self.assertEqual(
+ [
+ "bash",
+ "/lib/ramdisk-image-create",
+ "-o",
+ "ironic-python-agent",
+ "ironic-python-agent-ramdisk",
+ "extra-hardware",
+ ],
+ commands[1].command(),
+ )
+
+ @mock.patch("diskimage_builder.paths.get_path")
+ def test_build_commands_merged(self, mock_get_path):
+ mock_get_path.return_value = "/lib"
+ commands = dib.build_commands(
+ [
+ { # base definition
+ "imagename": "centos-minimal",
+ "elements": ["centos", "vm"],
+ "environment": {"foo": "bar", "zip": "zap"},
+ },
+ { # merge with previous when no imagename
+ "elements": ["devuser"],
+ "logfile": "centos-minimal.log",
+ },
+ { # merge when same imagename
+ "imagename": "centos-minimal",
+ "environment": {"foo": "baz", "one": "two"},
+ },
+ ]
+ )
+
+ self.assertEqual(1, len(commands))
+ self.assertEqual(
+ [
+ "bash",
+ "/lib/disk-image-create",
+ "-o",
+ "centos-minimal",
+ "--logfile",
+ "centos-minimal.log",
+ "centos",
+ "vm",
+ "devuser",
+ ],
+ commands[0].command(),
+ )
+
+ @mock.patch("diskimage_builder.paths.get_path")
+ def test_build_commands_all_arguments(self, mock_get_path):
+ mock_get_path.return_value = "/lib"
+ commands = dib.build_commands(
+ [
+ {
+ "arch": "amd64",
+ "imagename": "everyoption",
+ "types": ["qcow2"],
+ "debug-trace": 2,
+ "uncompressed": True,
+ "clear": True,
+ "logfile": "./logfile.log",
+ "checksum": True,
+ "image-size": 40,
+ "image-extra-size": 1,
+ "image-cache": "~/.cache/dib",
+ "max-online-resize": 1000,
+ "min-tmpfs": 7,
+ "mkfs-journal-size": 1,
+ "mkfs-options": "-D",
+ "no-tmpfs": True,
+ "offline": True,
+ "qemu-img-options": {"size": "10"},
+ "ramdisk-element": "dracut-ramdisk",
+ "install-type": "package",
+ "root-label": "root",
+ "docker-target": "everyoption:latest",
+ "packages": ["wget", "tmux"],
+ "skip-base": True,
+ "elements": ["centos", "vm"],
+ }
+ ]
+ )
+
+ self.assertEqual(
+ [
+ "bash",
+ "/lib/disk-image-create",
+ "-o",
+ "everyoption",
+ "-a",
+ "amd64",
+ "-t",
+ "qcow2",
+ "-x",
+ "-x",
+ "-u",
+ "-c",
+ "--logfile",
+ "./logfile.log",
+ "--checksum",
+ "--image-size",
+ "40",
+ "--image-extra-size",
+ "1",
+ "--image-cache",
+ "~/.cache/dib",
+ "--max-online-resize",
+ "1000",
+ "--min-tmpfs",
+ "7",
+ "--mkfs-journal-size",
+ "1",
+ "--mkfs-options",
+ "-D",
+ "--no-tmpfs",
+ "--offline",
+ "--qemu-img-options",
+ "size=10",
+ "--root-label",
+ "root",
+ "--ramdisk-element",
+ "dracut-ramdisk",
+ "--install-type",
+ "package",
+ "--docker-target",
+ "everyoption:latest",
+ "-p",
+ "wget,tmux",
+ "-n",
+ "centos",
+ "vm",
+ ],
+ commands[0].command(),
+ )
+
+ def write_image_definition(self):
+ image_def = [
+ {
+ "imagename": "centos-minimal",
+ "elements": ["centos", "vm"],
+ },
+ {
+ "imagename": "ironic-python-agent",
+ "ramdisk": True,
+ "elements": [
+ "ironic-python-agent-ramdisk",
+ "extra-hardware",
+ ],
+ },
+ ]
+ with tempfile.NamedTemporaryFile(delete=False) as deffile:
+ self.addCleanup(os.remove, deffile.name)
+ self.filelist = [deffile.name]
+ with open(deffile.name, "w") as f:
+ f.write(yaml.dump(image_def))
+ return deffile.name
+
+ @mock.patch("diskimage_builder.paths.get_path")
+ @mock.patch("diskimage_builder.diskimage_builder.get_args")
+ @mock.patch("subprocess.Popen")
+ def test_main_dry_run(self, mock_popen, mock_get_args, mock_get_path):
+ mock_get_path.return_value = "/lib"
+ mock_get_args.return_value = mock.Mock(
+ dry_run=True, files=[self.write_image_definition()]
+ )
+ dib.main()
+ mock_popen.assert_not_called()
+
+ @mock.patch("diskimage_builder.paths.get_path")
+ @mock.patch("diskimage_builder.diskimage_builder.get_args")
+ @mock.patch("subprocess.Popen")
+ def test_main(self, mock_popen, mock_get_args, mock_get_path):
+ mock_get_path.return_value = "/lib"
+ mock_get_args.return_value = mock.Mock(
+ dry_run=False,
+ files=[self.write_image_definition()],
+ stop_on_failure=False,
+ )
+
+ process = mock.Mock()
+ process.returncode = 0
+ mock_popen.return_value = process
+
+ dib.main()
+ self.assertEqual(2, mock_popen.call_count)
+ mock_popen.assert_has_calls(
+ [
+ mock.call(
+ [
+ "bash",
+ "/lib/disk-image-create",
+ "-o",
+ "centos-minimal",
+ "centos",
+ "vm",
+ ],
+ env=mock.ANY,
+ ),
+ mock.call(
+ [
+ "bash",
+ "/lib/ramdisk-image-create",
+ "-o",
+ "ironic-python-agent",
+ "ironic-python-agent-ramdisk",
+ "extra-hardware",
+ ],
+ env=mock.ANY,
+ ),
+ ],
+ any_order=True,
+ )
+
+ @mock.patch("diskimage_builder.paths.get_path")
+ @mock.patch("diskimage_builder.diskimage_builder.get_args")
+ @mock.patch("subprocess.Popen")
+ def test_main_stop_on_failure(
+ self, mock_popen, mock_get_args, mock_get_path
+ ):
+ mock_get_path.return_value = "/lib"
+ mock_get_args.return_value = mock.Mock(
+ dry_run=False,
+ files=[self.write_image_definition()],
+ stop_on_failure=True,
+ )
+
+ process = mock.Mock()
+ process.returncode = -1
+ mock_popen.return_value = process
+
+ e = self.assertRaises(subprocess.CalledProcessError, dib.main)
+ self.assertEqual(1, mock_popen.call_count)
+ self.assertEqual(-1, e.returncode)
+
+ @mock.patch("diskimage_builder.paths.get_path")
+ @mock.patch("diskimage_builder.diskimage_builder.get_args")
+ @mock.patch("subprocess.Popen")
+ def test_main_continue_on_failure(
+ self, mock_popen, mock_get_args, mock_get_path
+ ):
+ mock_get_path.return_value = "/lib"
+ mock_get_args.return_value = mock.Mock(
+ dry_run=False,
+ files=[self.write_image_definition()],
+ stop_on_failure=False,
+ )
+
+ process = mock.Mock()
+ process.returncode.side_effect = -1
+ mock_popen.return_value = process
+
+ self.assertRaises(subprocess.CalledProcessError, dib.main)
+ self.assertEqual(2, mock_popen.call_count)
diff --git a/doc/source/developer/components.rst b/doc/source/developer/components.rst
index df9b675..4f213b8 100644
--- a/doc/source/developer/components.rst
+++ b/doc/source/developer/components.rst
@@ -24,6 +24,60 @@ Components
Ironic no longer supports images created like this.
+`diskimage-builder [--dry-run] [--stop-on-failure] [--help] filename.yaml [filename2.yaml...]`
+
+ A YAML defined wrapper over `disk-image-create` and `ramdisk-image-create`.
+
+ To generate kernel+ramdisk pair for use with nova-baremetal, specify the YAML:
+
+ .. code-block:: yaml
+
+ - imagename: deploy.ramdisk
+ ramdisk: true
+ elements:
+ - deploy-baremetal
+
+ Duplicate `imagename` entries are merged into a single entry, allowing customizations over
+ a base image definition. If an `imagename` is missing, the `imagename` from the previous
+ entry is implied:
+
+ .. code-block:: yaml
+
+ # base image definition
+ - imagename: output.qcow
+ elements:
+ - vm
+ - block-device-gpt
+ - ubuntu-minimal
+ debug-trace: 1
+ environment:
+ DIB_IMAGE_SIZE: '10'
+
+ # debug logging customization
+ - imagename: output.qcow
+ debug-trace: 2
+
+ # adding element customization
+ - elements:
+ - devuser
+ environment:
+ DIB_DEV_USER_USERNAME: 'myuser'
+ DIB_DEV_USER_PWDLESS_SUDO: 'Yes'
+ DIB_DEV_USER_AUTHORIZED_KEYS: '/home/myuser/.ssh/id_rsa.pub'
+
+ # resulting image entry which will be built
+ - imagename: output.qcow
+ elements:
+ - vm
+ - block-device-gpt
+ - ubuntu-minimal
+ - devuser
+ debug-trace: 2
+ environment:
+ DIB_DEV_USER_USERNAME: 'myuser'
+ DIB_DEV_USER_PWDLESS_SUDO: 'Yes'
+ DIB_DEV_USER_AUTHORIZED_KEYS: '/home/myuser/.ssh/id_rsa.pub'
+ DIB_IMAGE_SIZE: '10'
`element-info`
diff --git a/doc/source/user_guide/building_an_image.rst b/doc/source/user_guide/building_an_image.rst
index 97c9d2f..fbdb107 100644
--- a/doc/source/user_guide/building_an_image.rst
+++ b/doc/source/user_guide/building_an_image.rst
@@ -19,6 +19,24 @@ The following command will start our image build (distro must be either
This will create a qcow2 file 'image.qcow2' which can then be booted.
+Images can also be defined with YAML and built with the `diskimage-builder`.
+
+With an `image.yaml` file containing:
+
+.. code-block:: yaml
+
+ - elements:
+ - <distro>
+ - vm
+
+An image is built with:
+
+::
+
+ diskimage-builder image.yaml
+
+Run `diskimage-builder --help` full description of the YAML attributes supported.
+
Elements
--------
@@ -79,6 +97,13 @@ There are currently two defaults:
disk-image-create -o output.qcow vm block-device-gpt ubuntu-minimal
+ Or with `diskimage-builder` YAML
+
+ .. code-block:: yaml
+
+ - imagename: output.qcow
+ elements: [vm, block-device-gpt, ubuntu-minimal]
+
* When not using the ``vm`` element a plain filesystem image, without
any partitioning, is created.
diff --git a/doc/source/user_guide/installation.rst b/doc/source/user_guide/installation.rst
index 2ffe2c7..80a1671 100644
--- a/doc/source/user_guide/installation.rst
+++ b/doc/source/user_guide/installation.rst
@@ -7,8 +7,8 @@ to keep it separate. For details, see the installation section in the
:ref:`dev_install`.
Once installed, you will be able to :doc:`build images
-<building_an_image>` using ``disk-image-create`` and the elements
-included in the main ``diskimage-builder`` repository.
+<building_an_image>` using ``disk-image-create`` or ``diskimage-builder``
+and the elements included in the main ``diskimage-builder`` repository.
Requirements
diff --git a/lower-constraints.txt b/lower-constraints.txt
index 78efd47..cd45a5a 100644
--- a/lower-constraints.txt
+++ b/lower-constraints.txt
@@ -13,6 +13,7 @@ imagesize==0.7.1
iso8601==0.1.11
isort==4.3.4
Jinja2==2.10
+jsonschema==3.0.2
keystoneauth1==3.4.0
lazy-object-proxy==1.3.1
linecache2==1.0.0
diff --git a/releasenotes/notes/Fix-ubuntu-minimal-not-running-autoremove-7a4e31de2a525f46.yaml b/releasenotes/notes/Fix-ubuntu-minimal-not-running-autoremove-7a4e31de2a525f46.yaml
new file mode 100644
index 0000000..ce25852
--- /dev/null
+++ b/releasenotes/notes/Fix-ubuntu-minimal-not-running-autoremove-7a4e31de2a525f46.yaml
@@ -0,0 +1,5 @@
+---
+fixes:
+ - |
+ Fixed the ubuntu-minimal target to also run autoremove at the end of an
+ image build.
diff --git a/releasenotes/notes/add-fips-element-a5a3e0e3c653f923.yaml b/releasenotes/notes/add-fips-element-a5a3e0e3c653f923.yaml
new file mode 100644
index 0000000..abbc22c
--- /dev/null
+++ b/releasenotes/notes/add-fips-element-a5a3e0e3c653f923.yaml
@@ -0,0 +1,12 @@
+---
+features:
+ - |
+ Adds a ``fips`` element which attempts to enable FIPS mode configuration
+ into the disk image being created.
+fixes:
+ - |
+ Fixes a possible case with a FIPS enabled disk image where the
+ cryptographic policies may be applied for enforcement of FIPS mode,
+ but the underlying kernel command line may be missing. This in particular
+ was discovered when testing on Rocky Linux. We now test, and add the FIPS
+ kernel command line flag if it is otherwise enabled.
diff --git a/releasenotes/notes/containerfile-host-networking-0691f3be5c6b11b6.yaml b/releasenotes/notes/containerfile-host-networking-0691f3be5c6b11b6.yaml
new file mode 100644
index 0000000..876e0bd
--- /dev/null
+++ b/releasenotes/notes/containerfile-host-networking-0691f3be5c6b11b6.yaml
@@ -0,0 +1,6 @@
+---
+upgrade:
+ - |
+ The default networking in the ``containerfile`` element is
+ switched to ``host`` as we have found that more reliable in
+ generating the initial chroot images.
diff --git a/releasenotes/notes/dib-command-a190f41cbd572b4b.yaml b/releasenotes/notes/dib-command-a190f41cbd572b4b.yaml
new file mode 100644
index 0000000..088526c
--- /dev/null
+++ b/releasenotes/notes/dib-command-a190f41cbd572b4b.yaml
@@ -0,0 +1,8 @@
+---
+features:
+ - |
+ A new command ``diskimage-builder`` is now provided (also aliased to
+ ``dib``). It provides a YAML file based interface to ``disk-image-create``
+ and ``ramdisk-image-create``. All arguments can be specified as yaml
+ dictionary entries, along with environment variable overrides which are
+ applied over the provided environment. \ No newline at end of file
diff --git a/releasenotes/notes/fix-grub-boot-kernel-commandline-1f94e49884c517c0.yaml b/releasenotes/notes/fix-grub-boot-kernel-commandline-1f94e49884c517c0.yaml
new file mode 100644
index 0000000..51682fe
--- /dev/null
+++ b/releasenotes/notes/fix-grub-boot-kernel-commandline-1f94e49884c517c0.yaml
@@ -0,0 +1,10 @@
+---
+fixes:
+ - |
+ Fixes the GRUB2 bootloader kernel command line where a prior ``boot``
+ parameter could cause issues with bootloader configuration when
+ an image is rebuilt and the ``bootloader`` element is utilized.
+ We now remove any prior ``boot`` parameter in */etc/default/grub*
+ when executing the ``bootloader`` element, and then assert a
+ valid entry ``boot`` parameter if a */boot* partition is defined
+ as part of the image build.
diff --git a/releasenotes/notes/swap_support-9ac267f56a0c0424.yaml b/releasenotes/notes/swap_support-9ac267f56a0c0424.yaml
new file mode 100644
index 0000000..56df0c2
--- /dev/null
+++ b/releasenotes/notes/swap_support-9ac267f56a0c0424.yaml
@@ -0,0 +1,4 @@
+---
+features:
+ - |
+ Adds swap as a valid "filesystem" for block devices
diff --git a/requirements.txt b/requirements.txt
index fa0d5f8..067d95f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,3 +8,4 @@ PyYAML>=3.12 # MIT
stevedore>=1.20.0 # Apache-2.0
# NOTE(ianw) in here because dib-lint uses flake8
flake8<6.0.0,>=3.6.0 # MIT
+jsonschema>=3.0.2 # MIT
diff --git a/setup.cfg b/setup.cfg
index 383990f..1d1e095 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -32,6 +32,7 @@ data_files =
console_scripts =
disk-image-create = diskimage_builder.disk_image_create:main
ramdisk-image-create = diskimage_builder.disk_image_create:main
+ diskimage-builder = diskimage_builder.diskimage_builder:main
diskimage_builder.block_device.plugin =
local_loop = diskimage_builder.block_device.level0.localloop:LocalLoop
partitioning = diskimage_builder.block_device.level1.partitioning:Partitioning
diff --git a/tests/run_functests.sh b/tests/run_functests.sh
index bcd1795..cfb388e 100755
--- a/tests/run_functests.sh
+++ b/tests/run_functests.sh
@@ -6,7 +6,7 @@ set -o pipefail
BASE_DIR=$(cd $(dirname "$0")/.. && pwd)
# then execute tests for elements
-export DIB_CMD="disk-image-create"
+export DIB_CMD="diskimage-builder"
export DIB_ELEMENTS=$(python -c '
import diskimage_builder.paths
diskimage_builder.paths.show_path("elements")')
@@ -111,13 +111,11 @@ function wait_minus_n {
# in results which tests have failed.
function logfile_status {
local status="$1"
- local arg="$2"
- local filename
- if [[ -z "${arg// }" ]]; then
+ local filename="$2"
+ if [[ -z "${filename}" ]]; then
return
fi
- filename="$(echo $arg | cut -f2 -d' ')"
echo "Moving ${filename} to ${filename/.log/.$status.log}"
mv "$filename" ${filename/.log/.$status.log}
}
@@ -132,25 +130,30 @@ function run_disk_element_test() {
local output_format="$4"
local logfile="$5"
- local use_tmp_flag=""
local dest_dir=$(mktemp -d)
if [[ ${KEEP_OUTPUT} -ne 1 ]]; then
trap "rm -rf $dest_dir" EXIT
fi
- if [ "${dont_use_tmp}" = "yes" ]; then
- use_tmp_flag="--no-tmpfs"
- fi
+ cat >> $dest_dir/image.yaml << EOF
+- imagename: $dest_dir/image
+ debug-trace: 1
+ types: [$output_format]
+ no-tmpfs: $dont_use_tmp
+ logfile: $logfile
+ skip-base: yes
+ elements:
+ - $element
+ - $test_element
+ environment:
+ DIB_SHOW_IMAGE_USAGE: "1"
+EOF
if break="after-error" break_outside_target=1 \
break_cmd="cp -v \$TMP_MOUNT_PATH/tmp/dib-test-should-fail ${dest_dir} || true" \
- DIB_SHOW_IMAGE_USAGE=1 \
ELEMENTS_PATH=$DIB_ELEMENTS/$element/test-elements \
- $DIB_CMD -x -t ${output_format} \
- ${use_tmp_flag} \
- ${logfile} \
- -o $dest_dir/image -n $element $test_element 2>&1 \
+ $DIB_CMD $dest_dir/image.yaml 2>&1 \
| log_with_prefix "${element}/${test_element}"; then
if [[ "qcow2" =~ "$output_format" ]]; then
@@ -212,16 +215,18 @@ function run_ramdisk_element_test() {
local logfile="$5"
local dest_dir=$(mktemp -d)
- local use_tmp_flag=""
- if [ "${dont_use_tmp}" = "yes" ]; then
- use_tmp_flag="--no-tmpfs"
- fi
+ cat >> $dest_dir/image.yaml << EOF
+- imagename: $dest_dir/image
+ debug-trace: 1
+ no-tmpfs: $dont_use_tmp
+ logfile: $logfile
+ elements:
+ - $element
+ - $test_element
+EOF
if ELEMENTS_PATH=$DIB_ELEMENTS/$element/test-elements \
- $DIB_CMD -x -o ${dest_dir}/image \
- ${logfile} \
- ${use_tmp_flag} \
- ${element} ${test_element} 2>&1 \
+ $DIB_CMD $dest_dir/image.yaml 2>&1 \
| log_with_prefix "${element}/${test_element}"; then
# TODO(dtantsur): test also kernel presence once we sort out its naming
# problem (vmlinuz vs kernel)
@@ -416,9 +421,9 @@ for test in "${TESTS_TO_RUN[@]}"; do
element_output=$(cat ${element_output_override})
fi
- log_argument=' '
+ log_argument=''
if [[ -n "${LOG_DIRECTORY}" ]]; then
- log_argument="--logfile ${LOG_DIRECTORY}/${element}_${test_element}.log"
+ log_argument="${LOG_DIRECTORY}/${element}_${test_element}.log"
fi
echo "Running $test ($element_type)"
diff --git a/tox.ini b/tox.ini
index b3394a7..f400c0c 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,12 +1,10 @@
[tox]
envlist = pep8,linters,py3
minversion = 3.18.0
-skipsdist = True
ignore_basepython_conflict = True
[testenv]
usedevelop = True
-basepython = python3
deps=
-r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
@@ -32,7 +30,6 @@ envdir = {toxworkdir}/venv
commands = {toxinidir}/tests/run_functests.sh {posargs}
[testenv:cover]
-basepython = python3
allowlist_externals = find
setenv =
PYTHON=coverage run --source diskimage_builder --parallel-mode
@@ -50,7 +47,6 @@ deps=
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/doc/requirements.txt
-basepython = python3
allowlist_externals =
rm
commands =