From 43d4dfcf054f47fd3fa6962bbd6414bcf653c8d9 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Fri, 19 Jan 2024 10:21:25 -0800 Subject: [PATCH 01/20] Change the ebsnvme-id script from Python to Bash (using nvme-cli) --- ebsnvme-id | 327 ++++++++++++++++++++++++++--------------------------- 1 file changed, 160 insertions(+), 167 deletions(-) mode change 100755 => 100644 ebsnvme-id diff --git a/ebsnvme-id b/ebsnvme-id old mode 100755 new mode 100644 index 972e938..b5f16c4 --- a/ebsnvme-id +++ b/ebsnvme-id @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/bash # Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved. # @@ -6,169 +6,162 @@ # for the specific language governing permissions and limitations under # the License. -""" -Usage: -Read EBS device information and provide information about -the volume. -""" - -from __future__ import print_function -import argparse -from ctypes import Structure, c_uint8, c_uint16, \ - c_uint32, c_uint64, c_char, addressof, sizeof -from fcntl import ioctl -import sys - -NVME_ADMIN_IDENTIFY = 0x06 -NVME_IOCTL_ADMIN_CMD = 0xC0484E41 -AMZN_NVME_VID = 0x1D0F -AMZN_NVME_EBS_MN = "Amazon Elastic Block Store" - - -class nvme_admin_command(Structure): - _pack_ = 1 - _fields_ = [("opcode", c_uint8), # op code - ("flags", c_uint8), # fused operation - ("cid", c_uint16), # command id - ("nsid", c_uint32), # namespace id - ("reserved0", c_uint64), - ("mptr", c_uint64), # metadata pointer - ("addr", c_uint64), # data pointer - ("mlen", c_uint32), # metadata length - ("alen", c_uint32), # data length - ("cdw10", c_uint32), - ("cdw11", c_uint32), - ("cdw12", c_uint32), - ("cdw13", c_uint32), - ("cdw14", c_uint32), - ("cdw15", c_uint32), - ("reserved1", c_uint64)] - - -class nvme_identify_controller_amzn_vs(Structure): - _pack_ = 1 - _fields_ = [("bdev", c_char * 32), # block device name - ("reserved0", c_char * (1024 - 32))] - - -class nvme_identify_controller_psd(Structure): - _pack_ = 1 - _fields_ = [("mp", c_uint16), # maximum power - ("reserved0", c_uint16), - ("enlat", c_uint32), # entry latency - ("exlat", c_uint32), # exit latency - ("rrt", c_uint8), # relative read throughput - ("rrl", c_uint8), # relative read latency - ("rwt", c_uint8), # relative write throughput - ("rwl", c_uint8), # relative write latency - ("reserved1", c_char * 16)] - - -class nvme_identify_controller(Structure): - _pack_ = 1 - _fields_ = [("vid", c_uint16), # PCI Vendor ID - ("ssvid", c_uint16), # PCI Subsystem Vendor ID - ("sn", c_char * 20), # Serial Number - ("mn", c_char * 40), # Module Number - ("fr", c_char * 8), # Firmware Revision - ("rab", c_uint8), # Recommend Arbitration Burst - ("ieee", c_uint8 * 3), # IEEE OUI Identifier - ("mic", c_uint8), # Multi-Interface Capabilities - ("mdts", c_uint8), # Maximum Data Transfer Size - ("reserved0", c_uint8 * (256 - 78)), - ("oacs", c_uint16), # Optional Admin Command Support - ("acl", c_uint8), # Abort Command Limit - ("aerl", c_uint8), # Asynchronous Event Request Limit - ("frmw", c_uint8), # Firmware Updates - ("lpa", c_uint8), # Log Page Attributes - ("elpe", c_uint8), # Error Log Page Entries - ("npss", c_uint8), # Number of Power States Support - ("avscc", c_uint8), # Admin Vendor Specific Command Configuration # noqa - ("reserved1", c_uint8 * (512 - 265)), - ("sqes", c_uint8), # Submission Queue Entry Size - ("cqes", c_uint8), # Completion Queue Entry Size - ("reserved2", c_uint16), - ("nn", c_uint32), # Number of Namespaces - ("oncs", c_uint16), # Optional NVM Command Support - ("fuses", c_uint16), # Fused Operation Support - ("fna", c_uint8), # Format NVM Attributes - ("vwc", c_uint8), # Volatile Write Cache - ("awun", c_uint16), # Atomic Write Unit Normal - ("awupf", c_uint16), # Atomic Write Unit Power Fail - ("nvscc", c_uint8), # NVM Vendor Specific Command Configuration # noqa - ("reserved3", c_uint8 * (704 - 531)), - ("reserved4", c_uint8 * (2048 - 704)), - ("psd", nvme_identify_controller_psd * 32), # Power State Descriptor # noqa - ("vs", nvme_identify_controller_amzn_vs)] # Vendor Specific - - -class ebs_nvme_device: - def __init__(self, device): - self.device = device - self.ctrl_identify() - - def _nvme_ioctl(self, id_response, id_len): - admin_cmd = nvme_admin_command(opcode=NVME_ADMIN_IDENTIFY, - addr=id_response, - alen=id_len, - cdw10=1) - - with open(self.device, "r") as nvme: - ioctl(nvme, NVME_IOCTL_ADMIN_CMD, admin_cmd) - - def ctrl_identify(self): - self.id_ctrl = nvme_identify_controller() - self._nvme_ioctl(addressof(self.id_ctrl), sizeof(self.id_ctrl)) - - if self.id_ctrl.vid != AMZN_NVME_VID \ - or self.id_ctrl.mn.decode().strip() != AMZN_NVME_EBS_MN: - raise TypeError("[ERROR] Not an EBS device: '{0}'".format(self.device)) # noqa - - def get_volume_id(self): - vol = self.id_ctrl.sn.decode() - - if vol.startswith("vol") and vol[3] != "-": - vol = "vol-" + vol[3:] - - return vol - - def get_block_device(self, stripped=False): - dev = self.id_ctrl.vs.bdev.decode().strip() - - if stripped and dev.startswith("/dev/"): - dev = dev[5:] - - return dev - - -if __name__ == "__main__": - parser = \ - argparse.ArgumentParser(description="Reads EBS information from NVMe devices.") # noqa - parser.add_argument("device", nargs=1, help="Device to query") - - display = parser.add_argument_group("Display Options") - display.add_argument("-v", "--volume", action="store_true", - help="Return volume-id") - display.add_argument("-b", "--block-dev", action="store_true", - help="Return block device mapping") - display.add_argument("-u", "--udev", action="store_true", - help="Output data in format suitable for udev rules") - - if len(sys.argv) < 2: - parser.print_help() - sys.exit(1) - - args = parser.parse_args() - - get_all = not (args.udev or args.volume or args.block_dev) - - try: - dev = ebs_nvme_device(args.device[0]) - except (IOError, TypeError) as err: - print(err, file=sys.stderr) - sys.exit(1) - - if get_all or args.volume: - print("Volume ID: {0}".format(dev.get_volume_id())) - if get_all or args.block_dev or args.udev: - print(dev.get_block_device(args.udev)) +# Bash/Unix implementation of ebsnvme-id that requires nvme-cli >= 1.13 +# Since this has to run inside initramfs, this is not using getopt/getopts. + +# Change this in case your distro puts nvme-cli in a different location +NVME=/usr/sbin/nvme + +# The EBS model name +EBS_MN="Amazon Elastic Block Store" + +## +# Ensures that the kernel device name in $1 is actually an EBS volume. +ensure_ebs_volume() { + local device=$1 + local mn + + if [[ ! -b /dev/$device ]]; then + echo "[ERROR] /dev/$device is not a block device" >&2 + exit 1 + fi + + mn="$(read_nvme_attr "$device" mn || printf "")" + + if [[ $mn != "${EBS_MN}" ]]; then + echo "[ERROR] /dev/$device is not an EBS device, but is $mn" >&2 + exit 1 + fi +} + +## +# Prints the block device mapping name for the device specified in $1 +print_block_device_mapping() { + local device=$1 + local bdev + + ensure_ebs_volume "$device" + + bdev=$(read_nvme_attr "$device" bdev) + + if [[ -z $bdev ]]; then + echo "[ERROR] /dev/$device has no block device mapping available" >&2 + exit 1 + fi + + echo "${bdev}" +} + +## +# Prints udev env vars for the device specified in $1 +print_udev_env() { + local device=$1 + local bdev + local volid + + ensure_ebs_volume "$device" + + bdev=$(read_nvme_attr "$device" bdev) + volid=$(read_volume_id "$device") + + if [[ -z $bdev || -z $volid ]]; then + echo "[ERROR] /dev/$device cannot determine udev environment" >&2 + exit 1 + fi + + echo "_EC2_BLOCK_DEVICE_MAPPING=${bdev}" + echo "_EBS_VOLUME_ID=${volid}" +} + +## +# Prints the volume ID for the device specified in $1 +print_volume_id() { + local device=$1 + local vol_id + + vol_id=$(read_volume_id "$device") + + echo "Volume ID: ${vol_id}" +} + +## +# Reads the NVMe attribute specified by $2 from the device specified in $1 +read_nvme_attr() { + local device=$1 + local nvme_attr=$2 + + ${NVME} amzn id-ctrl "/dev/${device}" | while read -r line; do + if [[ $line =~ ^${nvme_attr}[[:space:]]*: ]]; then + printf "%s" "${line#*: }" + return 0 + fi + done + + return 1 +} + +## +# Reads the volume ID for the device specified in $1 and parses it into a +# regular EBS vol-abcdef12345 format. +read_volume_id() { + local device=$1 + local sn + + ensure_ebs_volume "$device" + + sn=$(read_nvme_attr "$device" sn) + + if [[ -z $sn ]]; then + echo "[ERROR] /dev/$device has no volume ID available" >&2 + exit 1 + fi + + # Strip the prefix, which is usually vol, but we should tolerate vol- too + local without_prefix=${sn#vol} + + # Print out vol-XXX after stripping the - prefix which is probably not present + printf "vol-%s" "${without_prefix#-}" +} + +## +# Prints program usage information and exits +usage() { + echo "usage: ebsnvme-id [OPTION] + +Reads EBS information from NVMe devices. + +Options: + -h show this help message and exit + -v DEVICE Return volume ID + -b DEVICE Return block device mapping + -u DEVICE Deprecated alias for -b DEVICE + -U DEVICE Output data in a format suitable to be used as an IMPORT{program} in a udev rule +" +} + +# Check if we have enough arguments +if [[ $# -ne 2 ]]; then + usage + exit 1 +fi + +# Name the arguments and strip any leading /dev +option="$1" +device="${2#/dev/}" + +# Parse options +case $option in + -U) + print_udev_env "$device" + ;; + -b | -u) + print_block_device_mapping "$device" + ;; + -v) + print_volume_id "$device" + ;; + *) + usage + exit 1 + ;; +esac From 7844e0226c11c1847a9ba55820ffc0e0ef15d38c Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Fri, 19 Jan 2024 10:21:37 -0800 Subject: [PATCH 02/20] Add .editorconfig --- .editorconfig | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..5780041 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 2 + +[Makefile] +indent_style = tab + +[*.{diff,md}] +trim_trailing_whitespace = false From 73f9c04651471419b84604cf1e797c7f601cb291 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Fri, 19 Jan 2024 12:27:37 -0800 Subject: [PATCH 03/20] Make the block device mapping name strip off any leading /dev/ --- ebsnvme-id | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/ebsnvme-id b/ebsnvme-id index b5f16c4..72d6016 100644 --- a/ebsnvme-id +++ b/ebsnvme-id @@ -38,18 +38,11 @@ ensure_ebs_volume() { # Prints the block device mapping name for the device specified in $1 print_block_device_mapping() { local device=$1 - local bdev - - ensure_ebs_volume "$device" + local block_device_name - bdev=$(read_nvme_attr "$device" bdev) - - if [[ -z $bdev ]]; then - echo "[ERROR] /dev/$device has no block device mapping available" >&2 - exit 1 - fi + block_device_name=$(read_block_device_name "$device") - echo "${bdev}" + echo "${block_device_name}" } ## @@ -59,9 +52,7 @@ print_udev_env() { local bdev local volid - ensure_ebs_volume "$device" - - bdev=$(read_nvme_attr "$device" bdev) + bdev=$(read_block_device_name "$device") volid=$(read_volume_id "$device") if [[ -z $bdev || -z $volid ]]; then @@ -84,6 +75,25 @@ print_volume_id() { echo "Volume ID: ${vol_id}" } +## +# Reads the block device name from the device specified in $1 and strips off +# any leading /dev/ that might be present +read_block_device_name() { + local device=$1 + local bdev + + ensure_ebs_volume "$device" + + bdev=$(read_nvme_attr "$device" bdev) + + if [[ -z $bdev ]]; then + echo "[ERROR] /dev/$device has no block device mapping available" >&2 + exit 1 + fi + + printf "%s" "${bdev#/dev/}" +} + ## # Reads the NVMe attribute specified by $2 from the device specified in $1 read_nvme_attr() { From 06694145bcc3cd527abb7a3953c3871bec7c13d4 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Fri, 19 Jan 2024 12:29:13 -0800 Subject: [PATCH 04/20] Update udev rules --- 70-ec2-nvme-devices.rules | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/70-ec2-nvme-devices.rules b/70-ec2-nvme-devices.rules index 6fae458..d6d301b 100644 --- a/70-ec2-nvme-devices.rules +++ b/70-ec2-nvme-devices.rules @@ -13,9 +13,15 @@ KERNEL=="nvme[0-9]*n[0-9]*", ENV{DEVTYPE}=="disk", ATTRS{serial}=="?*", ATTRS{mo KERNEL=="nvme[0-9]*n[0-9]*p[0-9]*", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?*", ATTRS{model}=="?*", IMPORT{program}="/usr/sbin/ec2nvme-nsid %k" KERNEL=="nvme[0-9]*n[0-9]*p[0-9]*", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?*", ATTRS{model}=="?*", ENV{_NS_ID}=="?*", SYMLINK+="disk/by-id/nvme-$attr{model}_$attr{serial}-ns-$env{_NS_ID}-part%n", OPTIONS+="string_escape=replace" -# ebs nvme devices -KERNEL=="nvme[0-9]*n[0-9]*", ENV{DEVTYPE}=="disk", ATTRS{model}=="Amazon Elastic Block Store", PROGRAM="/usr/sbin/ebsnvme-id -u /dev/%k", SYMLINK+="%c" -KERNEL=="nvme[0-9]*n[0-9]*p[0-9]*", ENV{DEVTYPE}=="partition", ATTRS{model}=="Amazon Elastic Block Store", PROGRAM="/usr/sbin/ebsnvme-id -u /dev/%k", SYMLINK+="%c%n" +# Import variables for EBS volumes +KERNEL=="nvme[0-9]*n[0-9]*", ENV{DEVTYPE}=="disk", ATTRS{model}=="Amazon Elastic Block Store", IMPORT{program}+="/usr/sbin/ebsnvme-id -U %k" +KERNEL=="nvme[0-9]*n[0-9]*p[0-9]*", ENV{DEVTYPE}=="partition", ATTRS{model}=="Amazon Elastic Block Store", IMPORT{program}+="/usr/sbin/ebsnvme-id -U %k" + +# Assign symlinks +KERNEL=="nvme[0-9]*n[0-9]*", ENV{DEVTYPE}=="disk", ATTRS{model}=="Amazon Elastic Block Store", ENV{_EC2_BLOCK_DEVICE_MAPPING}=="?*", SYMLINK+="$env{_EC2_BLOCK_DEVICE_MAPPING}" +KERNEL=="nvme[0-9]*n[0-9]*", ENV{DEVTYPE}=="disk", ATTRS{model}=="Amazon Elastic Block Store", ENV{_EBS_VOLUME_ID}=="?*", SYMLINK+="disk/by-id/ebs-$env{_EBS_VOLUME_ID}" +KERNEL=="nvme[0-9]*n[0-9]*p[0-9]*", ENV{DEVTYPE}=="partition", ATTRS{model}=="Amazon Elastic Block Store", ENV{_EC2_BLOCK_DEVICE_MAPPING}=="?*", SYMLINK+="$env{_EC2_BLOCK_DEVICE_MAPPING}$env{ID_PART_ENTRY_NUMBER}" +KERNEL=="nvme[0-9]*n[0-9]*p[0-9]*", ENV{DEVTYPE}=="partition", ATTRS{model}=="Amazon Elastic Block Store", ENV{_EBS_VOLUME_ID}=="?*", SYMLINK+="disk/by-id/ebs-$env{_EBS_VOLUME_ID}-part$env{ID_PART_ENTRY_NUMBER}" # Do not timeout I/O operations on EBS volumes. KERNEL=="nvme[0-9]*n[0-9]*", ENV{DEVTYPE}=="disk", ATTRS{model}=="Amazon Elastic Block Store", ATTR{queue/io_timeout}="4294967295" From 3f8b59446088f167bde2064a24cdbd8e8da18747 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Mon, 22 Jan 2024 15:42:08 -0800 Subject: [PATCH 05/20] Update manpage --- doc/ebsnvme-id.8 | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/doc/ebsnvme-id.8 b/doc/ebsnvme-id.8 index 0e04c3a..dbede45 100644 --- a/doc/ebsnvme-id.8 +++ b/doc/ebsnvme-id.8 @@ -5,32 +5,35 @@ \" of this license, visit \" http://creativecommons.org/licenses/by-sa/4.0/. \" SPDX-License-Identifier: CC-BY-SA-4.0 -.TH EBSNVME-ID 8 "May 4 2020" +.TH EBSNVME-ID 8 "Jan 19 2024" .SH NAME ebsnvme-id \- Reads and prints EBS information from NVMe devices .SH SYNOPSIS .B ebsnvme-id -.RI [ options ] " DEVICE" +.RI [ options ] .br .SH DESCRIPTION .B ebsnvme-id -uses the NVME Management Interface to read various metadata about -NVME-attached EBS storage volumes. It can be used to retrive the EBS +uses the NVMe Management Interface to read various metadata about +NVMe-attached EBS storage volumes. It can be used to retrive the EBS Volume ID or EC2 API device mapping value given the local block device name. .SH OPTIONS .TP -.B \-v, \-\-volume +.B \-v Return volume-id .TP -.B \-b, \-\-block-dev -Return block device mapping +.B \-b , \-u +Return block device mapping (\-u is a deprecated alias) .TP -.B \-u, \-\-udev -Output data in format suitable for udev rules +.B \-U +Output data for the device as udev environment environment variables +suitable for use with +.B IMPORT{program} +in a udev rule .TP -.B \-h, \-\-help +.B \-h Show summary of options. .SH SEE ALSO .BR nvme (1), From f365c36426d1493ffdcfdc36812618acaa530bff Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Mon, 22 Jan 2024 16:06:52 -0800 Subject: [PATCH 06/20] Modernize the spec --- amazon-ec2-utils.spec | 79 +++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 44 deletions(-) diff --git a/amazon-ec2-utils.spec b/amazon-ec2-utils.spec index 34332e8..d938217 100644 --- a/amazon-ec2-utils.spec +++ b/amazon-ec2-utils.spec @@ -4,17 +4,7 @@ Version: 2.2.0 Release: 1%{?dist} License: MIT Group: System Tools - -Source0: ec2-metadata -Source1: ec2udev-vbd -Source2: 51-ec2-hvm-devices.rules -Source16: 60-cdrom_id.rules -Source22: 70-ec2-nvme-devices.rules -Source23: ec2nvme-nsid -Source24: ebsnvme-id -Source25: 51-ec2-xen-vbd-devices.rules -Source26: 53-ec2-read-ahead-kb.rules - +Source: amazon-ec2-utils.tar.gz URL: https://github.com/aws/amazon-ec2-utils BuildArch: noarch Provides: ec2-utils = %{version}-%{release} @@ -22,63 +12,64 @@ Obsoletes: ec2-utils < 2.1 Provides: ec2-metadata = %{version}-%{release} Obsoletes: ec2-metadata <= 0.1 Requires: curl -Requires: python3 -BuildRequires: python3-devel -BuildRequires: systemd-rpm-macros +Requires: nvme-cli >= 1.13 +BuildRequires: gzip systemd-rpm-macros BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) %description -amazon-ec2-utils contains a set of utilities for running in ec2. +amazon-ec2-utils contains a set of utilities for running in EC2. %prep +%autosetup -c %build +# compress manpages +gzip -f -9 doc/*.8 %install -rm -rf $RPM_BUILD_ROOT -mkdir -p $RPM_BUILD_ROOT%{_bindir} -mkdir -p $RPM_BUILD_ROOT%{_udevrulesdir} -mkdir -p $RPM_BUILD_ROOT/%{_sbindir} -mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/udev/rules.d/ -mkdir -p $RPM_BUILD_ROOT%{_mandir}/man8/ - -install -m755 %{SOURCE0} $RPM_BUILD_ROOT%{_bindir} -install -m755 %{SOURCE1} $RPM_BUILD_ROOT/%{_sbindir} -install -m644 %{SOURCE2} $RPM_BUILD_ROOT%{_udevrulesdir} -install -m644 %{SOURCE25} $RPM_BUILD_ROOT%{_udevrulesdir} -install -m644 %{SOURCE26} $RPM_BUILD_ROOT%{_udevrulesdir} +# Directories +%{__install} -d -pm 755 %{buildroot}%{_bindir} +%{__install} -d -pm 755 %{buildroot}%{_mandir}/man8 +%{__install} -d -pm 755 %{buildroot}%{_sbindir} +%{__install} -d -pm 755 %{buildroot}%{_sysconfdir}/udev/rules.d +%{__install} -d -pm 755 %{buildroot}%{_udevrulesdir} + +# Scripts +%{__install} -pm 755 ebsnvme-id %{buildroot}%{_sbindir}/ebsnvme-id +%{__install} -pm 755 ec2-metadata %{buildroot}%{_bindir}/ec2-metadata +%{__install} -pm 755 ec2nvme-nsid %{buildroot}%{_sbindir}/ec2nvme-nsid +%{__install} -pm 755 ec2udev-vbd %{buildroot}%{_sbindir}/ec2udev-vbd + +# udev rules +%{__install} -pm 644 51-ec2-hvm-devices.rules %{buildroot}%{_udevrulesdir}/51-ec2-hvm-devices.rules +%{__install} -pm 644 51-ec2-xen-vbd-devices.rules %{buildroot}%{_udevrulesdir}/51-ec2-xen-vbd-devices.rules +%{__install} -pm 644 53-ec2-read-ahead-kb.rules %{buildroot}%{_udevrulesdir}/53-ec2-read-ahead-kb.rules +%{__install} -pm 644 70-ec2-nvme-devices.rules %{buildroot}%{_udevrulesdir}/70-ec2-nvme-devices.rules + # Install 60-cdrom_id.rules to /etc rather than %{_udevrulesdir} # because it is intended as an override of a systemd-provided rules # file: -install -m644 %{SOURCE16} $RPM_BUILD_ROOT%{_sysconfdir}/udev/rules.d/ - -#udev rules for nvme block devices and supporting scripts -install -m644 %{SOURCE22} $RPM_BUILD_ROOT%{_udevrulesdir} -install -m755 %{SOURCE23} $RPM_BUILD_ROOT%{_sbindir}/ec2nvme-nsid -install -m755 %{SOURCE24} $RPM_BUILD_ROOT/%{_sbindir} - -%check -%{python3} -m py_compile %{SOURCE24} - -%clean -rm -rf $RPM_BUILD_ROOT +%{__install} -pm 644 60-cdrom_id.rules %{buildroot}%{_sysconfdir}/udev/rules.d/60-cdrom_id.rules %files +%license LICENSE +%doc README.md %{_bindir}/ec2-metadata %{_sbindir}/ec2nvme-nsid %{_sbindir}/ebsnvme-id %{_sbindir}/ec2udev-vbd -/usr/lib/udev/rules.d/51-ec2-hvm-devices.rules -/usr/lib/udev/rules.d/51-ec2-xen-vbd-devices.rules -/usr/lib/udev/rules.d/53-ec2-read-ahead-kb.rules -/usr/lib/udev/rules.d/70-ec2-nvme-devices.rules -/etc/udev/rules.d/60-cdrom_id.rules +%{_udevrulesdir}/51-ec2-hvm-devices.rules +%{_udevrulesdir}/51-ec2-xen-vbd-devices.rules +%{_udevrulesdir}/53-ec2-read-ahead-kb.rules +%{_udevrulesdir}/70-ec2-nvme-devices.rules +%{_sysconfdir}/udev/rules.d/60-cdrom_id.rules %changelog * Thu Jan 18 2024 Keith Gable - 2.2.0-1 - Corrected issue where an ec2-metadata error was written to stdout - Change ec2nvme-nsid to use Bash string manipulation to improve performance and reliability +- Rewrite ebsnvme-id in Bash so it is usable in early boot * Mon Jun 5 2023 Guillaume Delacour - 2.2.0-1 - Add `--quiet` option to `ec2-metadata --help` output From f27aed1636828fc04272ee9eef5e2b242ac8b144 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Tue, 23 Jan 2024 14:51:39 -0800 Subject: [PATCH 07/20] Ignore .tar and .tar.gz files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..74a4c43 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.tar +*.tar.gz From eda4bf6c10961ba0a5a8da17fcf06f46e12f3ab8 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Tue, 23 Jan 2024 14:52:22 -0800 Subject: [PATCH 08/20] Choose a buildroot that is more consistent with other packages and also include man pages --- amazon-ec2-utils.spec | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/amazon-ec2-utils.spec b/amazon-ec2-utils.spec index d938217..27973ae 100644 --- a/amazon-ec2-utils.spec +++ b/amazon-ec2-utils.spec @@ -14,7 +14,7 @@ Obsoletes: ec2-metadata <= 0.1 Requires: curl Requires: nvme-cli >= 1.13 BuildRequires: gzip systemd-rpm-macros -BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) +BuildRoot: %{_tmppath}/%{name}-root %description amazon-ec2-utils contains a set of utilities for running in EC2. @@ -40,6 +40,10 @@ gzip -f -9 doc/*.8 %{__install} -pm 755 ec2nvme-nsid %{buildroot}%{_sbindir}/ec2nvme-nsid %{__install} -pm 755 ec2udev-vbd %{buildroot}%{_sbindir}/ec2udev-vbd +# man pages +%{__install} -pm 644 doc/ebsnvme-id.8.gz %{buildroot}%{_mandir}/man8/ebsnvme-id.8.gz +%{__install} -pm 644 doc/ec2-metadata.8.gz %{buildroot}%{_mandir}/man8/ec2-metadata.8.gz + # udev rules %{__install} -pm 644 51-ec2-hvm-devices.rules %{buildroot}%{_udevrulesdir}/51-ec2-hvm-devices.rules %{__install} -pm 644 51-ec2-xen-vbd-devices.rules %{buildroot}%{_udevrulesdir}/51-ec2-xen-vbd-devices.rules @@ -55,6 +59,8 @@ gzip -f -9 doc/*.8 %license LICENSE %doc README.md %{_bindir}/ec2-metadata +%{_mandir}/man8/ebsnvme-id.8.gz +%{_mandir}/man8/ec2-metadata.8.gz %{_sbindir}/ec2nvme-nsid %{_sbindir}/ebsnvme-id %{_sbindir}/ec2udev-vbd From cb95d7f90f245a22f5eaaf6b67ecb20cdd4a6915 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Tue, 23 Jan 2024 14:52:50 -0800 Subject: [PATCH 09/20] Add Dracut module --- dracut/dracut.conf | 7 +++++++ dracut/module-setup.sh | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 dracut/dracut.conf create mode 100644 dracut/module-setup.sh diff --git a/dracut/dracut.conf b/dracut/dracut.conf new file mode 100644 index 0000000..dde93c6 --- /dev/null +++ b/dracut/dracut.conf @@ -0,0 +1,7 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the MIT License. See the LICENSE accompanying this file +# for the specific language governing permissions and limitations under +# the License. + +add_dracutmodules+=" ec2-utils " diff --git a/dracut/module-setup.sh b/dracut/module-setup.sh new file mode 100644 index 0000000..3a50e96 --- /dev/null +++ b/dracut/module-setup.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the MIT License. See the LICENSE accompanying this file +# for the specific language governing permissions and limitations under +# the License. + +# called by dracut +check() { + # don't install this module unless the configuration explicitly requests it + return 255 +} + +# called by dracut +depends() { + echo bash udev-rules + return 0 +} + +# called by dracut +install() { + # Install udev rules + inst_rules \ + 51-ec2-hvm-devices.rules \ + 51-ec2-xen-vbd-devices.rules \ + 53-ec2-read-ahead-kb.rules \ + 70-ec2-nvme-devices.rules + + # Install scripts + inst_multiple \ + ebsnvme-id \ + ec2nvme-nsid \ + ec2udev-vbd +} From 574b563031e1c7cfb541e03db5822b5af513bf87 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Tue, 23 Jan 2024 14:52:59 -0800 Subject: [PATCH 10/20] Create sub-package for Dracut --- amazon-ec2-utils.spec | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/amazon-ec2-utils.spec b/amazon-ec2-utils.spec index 27973ae..9b86b52 100644 --- a/amazon-ec2-utils.spec +++ b/amazon-ec2-utils.spec @@ -31,8 +31,10 @@ gzip -f -9 doc/*.8 %{__install} -d -pm 755 %{buildroot}%{_bindir} %{__install} -d -pm 755 %{buildroot}%{_mandir}/man8 %{__install} -d -pm 755 %{buildroot}%{_sbindir} +%{__install} -d -pm 755 %{buildroot}%{_sysconfdir}/dracut.conf.d %{__install} -d -pm 755 %{buildroot}%{_sysconfdir}/udev/rules.d %{__install} -d -pm 755 %{buildroot}%{_udevrulesdir} +%{__install} -d -pm 755 %{buildroot}%{dracutlibdir}/modules.d/96ec2-utils # Scripts %{__install} -pm 755 ebsnvme-id %{buildroot}%{_sbindir}/ebsnvme-id @@ -55,6 +57,10 @@ gzip -f -9 doc/*.8 # file: %{__install} -pm 644 60-cdrom_id.rules %{buildroot}%{_sysconfdir}/udev/rules.d/60-cdrom_id.rules +# Dracut module +%{__install} -pm 644 dracut/dracut.conf %{buildroot}%{_sysconfdir}/dracut.conf.d/ec2-utils.conf +%{__install} -pm 755 dracut/module-setup.sh %{buildroot}%{dracutlibdir}/modules.d/96ec2-utils/module-setup.sh + %files %license LICENSE %doc README.md @@ -70,6 +76,22 @@ gzip -f -9 doc/*.8 %{_udevrulesdir}/70-ec2-nvme-devices.rules %{_sysconfdir}/udev/rules.d/60-cdrom_id.rules +%package dracut +Summary: Dracut module providing early boot support for EC2 devices +Requires: amazon-ec2-utils = %{version}-%{release} +Requires: dracut + +%description dracut +This subpackage contains the Dracut module that provides early boot support for EC2 +devices, like making EBS NVMe devices have names in /dev that match their EC2 block +device mapping names. + +%files dracut +%license LICENSE +%doc README.md +%{_sysconfdir}/dracut.conf.d/ec2-utils.conf +%{dracutlibdir}/modules.d/96ec2-utils/module-setup.sh + %changelog * Thu Jan 18 2024 Keith Gable - 2.2.0-1 - Corrected issue where an ec2-metadata error was written to stdout From cffd28c597c06b2fae8818cd69f22f0d4986566e Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Tue, 23 Jan 2024 14:56:31 -0800 Subject: [PATCH 11/20] Add a Makefile that builds the RPM --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..30aa648 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +.PHONY: rpm +rpm: + git archive --format=tar HEAD > amazon-ec2-utils.tar + gzip -f -9 amazon-ec2-utils.tar + rpmbuild --define "%_topdir $$(mktemp -d /tmp/amazon-linux-utils.rpm-XXXXXXXX)" -ta amazon-ec2-utils.tar.gz -v From 97e778d750aa427ce29fe4ca3662378733a222f2 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Tue, 23 Jan 2024 14:58:09 -0800 Subject: [PATCH 12/20] Copy the built RPMs into cwd --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 30aa648..1a209a2 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,8 @@ +RPM_BUILD_DIR = $(shell mktemp -d /tmp/amazon-linux-utils.rpm-XXXXXXXX) + .PHONY: rpm rpm: git archive --format=tar HEAD > amazon-ec2-utils.tar gzip -f -9 amazon-ec2-utils.tar - rpmbuild --define "%_topdir $$(mktemp -d /tmp/amazon-linux-utils.rpm-XXXXXXXX)" -ta amazon-ec2-utils.tar.gz -v + rpmbuild --define "%_topdir $(RPM_BUILD_DIR)" -ta amazon-ec2-utils.tar.gz -v + cp -v $(RPM_BUILD_DIR)/RPMS/*.rpm $(RPM_BUILD_DIR)/SRPMS/*.rpm . From 68ebc613415d40aee709dee75be5ed0e12cc64e2 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Tue, 23 Jan 2024 14:58:25 -0800 Subject: [PATCH 13/20] Also ignore *.rpm --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 74a4c43..63a543f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +*.rpm *.tar *.tar.gz From ea61796b962388117b846edb1df335a10343e468 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Tue, 23 Jan 2024 14:58:39 -0800 Subject: [PATCH 14/20] make cp overwrite --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1a209a2..82a4e5b 100644 --- a/Makefile +++ b/Makefile @@ -5,4 +5,4 @@ rpm: git archive --format=tar HEAD > amazon-ec2-utils.tar gzip -f -9 amazon-ec2-utils.tar rpmbuild --define "%_topdir $(RPM_BUILD_DIR)" -ta amazon-ec2-utils.tar.gz -v - cp -v $(RPM_BUILD_DIR)/RPMS/*.rpm $(RPM_BUILD_DIR)/SRPMS/*.rpm . + cp -fv $(RPM_BUILD_DIR)/RPMS/*.rpm $(RPM_BUILD_DIR)/SRPMS/*.rpm . From 89cf9b7e00d03d9a8b55ee20b11591106ad440ac Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Tue, 23 Jan 2024 15:00:54 -0800 Subject: [PATCH 15/20] Forgot to define dracutlibdir --- amazon-ec2-utils.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/amazon-ec2-utils.spec b/amazon-ec2-utils.spec index 9b86b52..acd15a8 100644 --- a/amazon-ec2-utils.spec +++ b/amazon-ec2-utils.spec @@ -1,3 +1,5 @@ +%define dracutlibdir %{_prefix}/lib/dracut + Name: amazon-ec2-utils Summary: A set of tools for running in EC2 Version: 2.2.0 From 136fc9d7acee19b73b8cfe46afbbba9ab3ddd8c6 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Tue, 23 Jan 2024 15:02:50 -0800 Subject: [PATCH 16/20] RPMs are in subdirectories by arch, oops --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 82a4e5b..032ff17 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ -RPM_BUILD_DIR = $(shell mktemp -d /tmp/amazon-linux-utils.rpm-XXXXXXXX) +RPM_BUILD_DIR := $(shell mktemp -d /tmp/amazon-linux-utils.rpm-XXXXXXXX) .PHONY: rpm rpm: git archive --format=tar HEAD > amazon-ec2-utils.tar gzip -f -9 amazon-ec2-utils.tar rpmbuild --define "%_topdir $(RPM_BUILD_DIR)" -ta amazon-ec2-utils.tar.gz -v - cp -fv $(RPM_BUILD_DIR)/RPMS/*.rpm $(RPM_BUILD_DIR)/SRPMS/*.rpm . + cp -fv $(RPM_BUILD_DIR)/RPMS/**/*.rpm $(RPM_BUILD_DIR)/SRPMS/*.rpm . From 064f86e08e738bc07bb8a7a8fff5cd0f4e5d5d3f Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Tue, 23 Jan 2024 15:08:02 -0800 Subject: [PATCH 17/20] Add license header --- Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile b/Makefile index 032ff17..0caffed 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,9 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the MIT License. See the LICENSE accompanying this file +# for the specific language governing permissions and limitations under +# the License. + RPM_BUILD_DIR := $(shell mktemp -d /tmp/amazon-linux-utils.rpm-XXXXXXXX) .PHONY: rpm From ea1d9f3fcdec5488aaff6c5677ef7a190e637a28 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Thu, 1 Feb 2024 12:00:23 -0800 Subject: [PATCH 18/20] Add changelog entry --- amazon-ec2-utils.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/amazon-ec2-utils.spec b/amazon-ec2-utils.spec index acd15a8..1be482b 100644 --- a/amazon-ec2-utils.spec +++ b/amazon-ec2-utils.spec @@ -100,6 +100,7 @@ device mapping names. - Change ec2nvme-nsid to use Bash string manipulation to improve performance and reliability - Rewrite ebsnvme-id in Bash so it is usable in early boot +- Add Dracut module to support block device naming in early boot * Mon Jun 5 2023 Guillaume Delacour - 2.2.0-1 - Add `--quiet` option to `ec2-metadata --help` output From b583408ebe94a69c4015c27f74aee87f7cffd1b2 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Wed, 7 Feb 2024 16:26:10 -0800 Subject: [PATCH 19/20] Oops, the printf made this fail in a real AMI --- ebsnvme-id | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ebsnvme-id b/ebsnvme-id index 72d6016..578231d 100644 --- a/ebsnvme-id +++ b/ebsnvme-id @@ -26,10 +26,10 @@ ensure_ebs_volume() { exit 1 fi - mn="$(read_nvme_attr "$device" mn || printf "")" + mn="$(read_nvme_attr "$device" mn)" - if [[ $mn != "${EBS_MN}" ]]; then - echo "[ERROR] /dev/$device is not an EBS device, but is $mn" >&2 + if [[ "$mn" != "${EBS_MN}" ]]; then + echo "[ERROR] /dev/$device is not an EBS device, but is ${mn:-}" >&2 exit 1 fi } From f8afb958dd27fd77c472f9e8f66b0572cf791a66 Mon Sep 17 00:00:00 2001 From: Keith Gable Date: Mon, 26 Feb 2024 11:22:46 -0800 Subject: [PATCH 20/20] Update ebsnvme-id --- ebsnvme-id | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ebsnvme-id b/ebsnvme-id index 578231d..3b930cd 100644 --- a/ebsnvme-id +++ b/ebsnvme-id @@ -55,7 +55,7 @@ print_udev_env() { bdev=$(read_block_device_name "$device") volid=$(read_volume_id "$device") - if [[ -z $bdev || -z $volid ]]; then + if [[ -z $bdev ]] || [[ -z $volid ]]; then echo "[ERROR] /dev/$device cannot determine udev environment" >&2 exit 1 fi