From f0dd2136323e7140b2a67b7cc3e5a6615fc2cdce Mon Sep 17 00:00:00 2001 From: Ben Cressey Date: Wed, 22 Mar 2023 23:32:28 +0000 Subject: [PATCH 1/2] os: create specialized partition UUID symlinks In certain cases, it is useful for systemd units to only operate on partitions that meet certain criteria. For example, "system" partitions found on unusual block devices might be ignored to avoid untested or undefined behavior at runtime. Signed-off-by: Ben Cressey Co-authored-by: Matthew Yeazel Co-authored-by: Erikson Tung --- packages/os/os.spec | 3 +++ packages/os/supplemental-storage.rules | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 packages/os/supplemental-storage.rules diff --git a/packages/os/os.spec b/packages/os/os.spec index 5f2ea083e9d..dd3fdae1e84 100644 --- a/packages/os/os.spec +++ b/packages/os/os.spec @@ -59,6 +59,7 @@ Source204: netdog-tmpfiles.conf # 3xx sources: udev rules Source300: ephemeral-storage.rules Source301: ebs-volumes.rules +Source302: supplemental-storage.rules BuildRequires: %{_cross_os}glibc-devel Requires: %{_cross_os}apiclient @@ -443,6 +444,7 @@ install -p -m 0644 %{S:204} %{buildroot}%{_cross_tmpfilesdir}/netdog.conf install -d %{buildroot}%{_cross_udevrulesdir} install -p -m 0644 %{S:300} %{buildroot}%{_cross_udevrulesdir}/80-ephemeral-storage.rules install -p -m 0644 %{S:301} %{buildroot}%{_cross_udevrulesdir}/81-ebs-volumes.rules +install -p -m 0644 %{S:302} %{buildroot}%{_cross_udevrulesdir}/82-supplemental-storage.rules %if %{with vmware_platform} install -p -m 0644 %{S:121} %{buildroot}%{_cross_unitdir} @@ -523,6 +525,7 @@ install -p -m 0644 %{S:121} %{buildroot}%{_cross_unitdir} %{_cross_bindir}/ghostdog %{_cross_udevrulesdir}/80-ephemeral-storage.rules %{_cross_udevrulesdir}/81-ebs-volumes.rules +%{_cross_udevrulesdir}/82-supplemental-storage.rules %files -n %{_cross_os}signpost %{_cross_bindir}/signpost diff --git a/packages/os/supplemental-storage.rules b/packages/os/supplemental-storage.rules new file mode 100644 index 00000000000..f72e9d239e2 --- /dev/null +++ b/packages/os/supplemental-storage.rules @@ -0,0 +1,24 @@ +# supplemental storage links: /dev/disk/by-volume-type-partuuid +# +# The purpose of the additional links is to encode what kind of backing device +# the partition resides on, for cases where systemd units need this information +# for conditional logic. + +ACTION=="remove", GOTO="supplemental_storage_end" +SUBSYSTEM!="block", GOTO="supplemental_storage_end" +ENV{DEVTYPE}!="partition", GOTO="supplemental_storage_end" + +# Only these drivers have "interesting" volume types. +KERNEL!="nvme*|xvd*|vd*", GOTO="supplemental_storage_end" + +# Set the volume type for each supported driver, annotating it with the volume +# sub-type, if any. +ENV{BOTTLEROCKET_VOLUME_TYPE}!="?*", KERNEL=="nvme*", ATTRS{model}=="Amazon EC2 NVMe Instance Storage*", ENV{BOTTLEROCKET_VOLUME_TYPE}="nvme-instance-store" +ENV{BOTTLEROCKET_VOLUME_TYPE}!="?*", KERNEL=="nvme*", ATTRS{model}=="Amazon Elastic Block Store*", ENV{BOTTLEROCKET_VOLUME_TYPE}="nvme-ebs" +ENV{BOTTLEROCKET_VOLUME_TYPE}!="?*", KERNEL=="nvme*", ENV{BOTTLEROCKET_VOLUME_TYPE}="nvme" +ENV{BOTTLEROCKET_VOLUME_TYPE}!="?*", KERNEL=="xvd*", ENV{BOTTLEROCKET_VOLUME_TYPE}="xen" +ENV{BOTTLEROCKET_VOLUME_TYPE}!="?*", KERNEL=="vd*", ENV{BOTTLEROCKET_VOLUME_TYPE}="virtio" + +ENV{ID_PART_ENTRY_UUID}=="?*" SYMLINK+="disk/by-volume-type-partuuid/$env{BOTTLEROCKET_VOLUME_TYPE}-$env{ID_PART_ENTRY_UUID}" + +LABEL="supplemental_storage_end" From e3d3fc6754c2f9023597f410671ecce6146778f0 Mon Sep 17 00:00:00 2001 From: Erikson Tung Date: Wed, 22 Mar 2023 10:26:22 -0700 Subject: [PATCH 2/2] release: special-case data partition handling We reconceptualize DATA-A and DATA-B as a set of preferred and fallback data partitions. The preferred partition will always get repart'd if the partition matching the preferred data partition GUID exists. The fallback partition only gets repart'd if we've confirmed that the data partition resides on a device that is not EBS or Xen virtual disk. We determine this by checking new device symlinks that indicates the storage device type. This avoids any behavior change for EC2 instance launches, even if additional size is allocated to the first EBS volume. This is done to support platforms like Snow, where the same AMI is used but a second volume is not available at launch. Since Snow does not handle EBS volumes in the same way, the symlink checks do not prevent the fallback partition on the first volume from being used. --- packages/release/release.spec | 8 +++--- ...b.service => repart-data-fallback.service} | 7 +++-- ....service => repart-data-preferred.service} | 4 +-- tools/partyplanner | 28 +++++++++++++------ tools/rpm2img | 2 +- 5 files changed, 32 insertions(+), 17 deletions(-) rename packages/release/{label-data-b.service => repart-data-fallback.service} (65%) rename packages/release/{label-data-a.service => repart-data-preferred.service} (88%) diff --git a/packages/release/release.spec b/packages/release/release.spec index 41bd23bff83..b3d1e86c960 100644 --- a/packages/release/release.spec +++ b/packages/release/release.spec @@ -57,8 +57,8 @@ Source1043: repart-local.service Source1044: mask-local-mnt.service Source1045: mask-local-opt.service Source1046: mask-local-var.service -Source1047: label-data-b.service -Source1048: label-data-a.service +Source1047: repart-data-preferred.service +Source1048: repart-data-fallback.service Source1049: prepare-local-fs.service # Services for kdump support @@ -225,8 +225,8 @@ ln -s preconfigured.target %{buildroot}%{_cross_unitdir}/default.target %{_cross_unitdir}/mask-local-opt.service %{_cross_unitdir}/mask-local-var.service %{_cross_unitdir}/root-.aws.mount -%{_cross_unitdir}/label-data-b.service -%{_cross_unitdir}/label-data-a.service +%{_cross_unitdir}/repart-data-preferred.service +%{_cross_unitdir}/repart-data-fallback.service %{_cross_unitdir}/prepare-local-fs.service %dir %{_cross_unitdir}/systemd-tmpfiles-setup.service.d %{_cross_unitdir}/systemd-tmpfiles-setup.service.d/00-debug.conf diff --git a/packages/release/label-data-b.service b/packages/release/repart-data-fallback.service similarity index 65% rename from packages/release/label-data-b.service rename to packages/release/repart-data-fallback.service index 49d7d4a5073..cbfc38dff04 100644 --- a/packages/release/label-data-b.service +++ b/packages/release/repart-data-fallback.service @@ -1,12 +1,15 @@ [Unit] -Description=Label data partition B +Description=Repart fallback data partition DefaultDependencies=no Conflicts=shutdown.target # Only run this if a partition labeled 'BOTTLEROCKET-DATA' does not exist already. ConditionPathIsSymbolicLink=!/dev/disk/by-partlabel/BOTTLEROCKET-DATA +# Only run this if the data partition is not on a Xen virtual device and also not on an EBS volume. +ConditionPathIsSymbolicLink=!/dev/disk/by-volume-type-partuuid/xen-69040874-417d-4e26-a764-7885f22007ea +ConditionPathIsSymbolicLink=!/dev/disk/by-volume-type-partuuid/nvme-ebs-69040874-417d-4e26-a764-7885f22007ea # Only run if this boot has never succeeded before ConditionFileNotEmpty=!/etc/has-boot-ever-succeeded -# This is the partition GUID for DATA-B data partition. +# This is the partition GUID for fallback data partition. Wants=dev-disk-by\x2dpartuuid-69040874\x2d417d\x2d4e26\x2da764\x2d7885f22007ea.device After=dev-disk-by\x2dpartuuid-69040874\x2d417d\x2d4e26\x2da764\x2d7885f22007ea.device diff --git a/packages/release/label-data-a.service b/packages/release/repart-data-preferred.service similarity index 88% rename from packages/release/label-data-a.service rename to packages/release/repart-data-preferred.service index 80033252995..2f2e878f3f0 100644 --- a/packages/release/label-data-a.service +++ b/packages/release/repart-data-preferred.service @@ -1,12 +1,12 @@ [Unit] -Description=Label data partition A +Description=Repart preferred data partition DefaultDependencies=no Conflicts=shutdown.target # Only run this if a partition labeled 'BOTTLEROCKET-DATA' does not exist already. ConditionPathIsSymbolicLink=!/dev/disk/by-partlabel/BOTTLEROCKET-DATA # Only run if this boot has never succeeded before ConditionFileNotEmpty=!/etc/has-boot-ever-succeeded -# This is the partition GUID for the DATA-A partition. +# This is the partition GUID for the preferred data partition. Wants=dev-disk-by\x2dpartuuid-5b94e8df\x2d28b8\x2d485c\x2d9d19\x2d362263b5944c.device After=dev-disk-by\x2dpartuuid-5b94e8df\x2d28b8\x2d485c\x2d9d19\x2d362263b5944c.device diff --git a/tools/partyplanner b/tools/partyplanner index 8ad839d68a5..d638319c87e 100755 --- a/tools/partyplanner +++ b/tools/partyplanner @@ -42,8 +42,8 @@ EFI_BACKUP_TYPECODE="B39CE39C-0A00-B4AB-2D11-F18F8237A21C" # Define partition GUIDs for the data partitions. We use the GUID for determining # which data partition to label and use at boot. -BOTTLEROCKET_DATA_A_PARTGUID="5b94e8df-28b8-485c-9d19-362263b5944c" -BOTTLEROCKET_DATA_B_PARTGUID="69040874-417d-4e26-a764-7885f22007ea" +BOTTLEROCKET_DATA_PREFERRED_PARTGUID="5b94e8df-28b8-485c-9d19-362263b5944c" +BOTTLEROCKET_DATA_FALLBACK_PARTGUID="69040874-417d-4e26-a764-7885f22007ea" ############################################################################### # Section 2: fixed size partitions and reservations @@ -255,10 +255,22 @@ set_partition_types() { set_partition_uuids() { local -n pp_uuid pp_uuid="${1:?}" - local uuid - for bank in A B ; do - uuid="BOTTLEROCKET_DATA_${bank}_PARTGUID" - uuid="${!uuid}" - pp_uuid["DATA-${bank}"]="${uuid}" - done + # Whether we're building a layout for a "split" image, where OS and data + # volumes are on separate disks, or a "unified" image, where they share the + # same disk. + partition_plan="${2:?}" + case "${partition_plan}" in + split) + pp_uuid["DATA-A"]="${BOTTLEROCKET_DATA_FALLBACK_PARTGUID}" + pp_uuid["DATA-B"]="${BOTTLEROCKET_DATA_PREFERRED_PARTGUID}" + ;; + unified) + pp_uuid["DATA-A"]="${BOTTLEROCKET_DATA_PREFERRED_PARTGUID}" + pp_uuid["DATA-B"]="${BOTTLEROCKET_DATA_FALLBACK_PARTGUID}" + ;; + *) + echo "unknown partition plan '${partition_plan}'" >&2 + exit 1 + ;; + esac } diff --git a/tools/rpm2img b/tools/rpm2img index aa93c03f3f7..480c2047b44 100755 --- a/tools/rpm2img +++ b/tools/rpm2img @@ -147,7 +147,7 @@ set_partition_sizes \ partsize partoff set_partition_labels partlabel set_partition_types parttype -set_partition_uuids partguid +set_partition_uuids partguid "${PARTITION_PLAN}" declare -a partargs for part in \