cloud-init/ci-Get-rid-of-gdisk-dependency.patch

176 lines
6.2 KiB
Diff
Raw Normal View History

From f1fdff22c356fcfb6ef546633e7872313dca36d1 Mon Sep 17 00:00:00 2001
From: Vitaly Kuznetsov <vkuznets@redhat.com>
Date: Wed, 7 Aug 2024 16:47:52 +0200
Subject: [PATCH 2/2] Get rid of gdisk dependency
RH-Author: Vitaly Kuznetsov <vkuznets@redhat.com>
RH-MergeRequest: 106: Get rid of gdisk dependency
RH-Jira: RHEL-36093
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
RH-Acked-by: Cathy Avery <cavery@redhat.com>
RH-Commit: [2/2] 7814ff343d4f8e7db95ca1853ea0079fe577354a (vkuznets/cloud-init)
gdisk is not going to be shipped in RHEL10 as sfdisk is perfectly capable
of dealing with GPT partition tables. cloud-init's upstream still relies on
sgdisk for GPT and is reluctant to do the switch, do this downstream only
for now.
X-downstream-only: true
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
.distro/cloud-init.spec | 1 -
cloudinit/config/cc_disk_setup.py | 98 +++++++++++++------------------
2 files changed, 42 insertions(+), 57 deletions(-)
diff --git a/cloudinit/config/cc_disk_setup.py b/cloudinit/config/cc_disk_setup.py
index fa6a52d3..7638b425 100644
--- a/cloudinit/config/cc_disk_setup.py
+++ b/cloudinit/config/cc_disk_setup.py
@@ -10,6 +10,7 @@
import logging
import os
import shlex
+import json
from textwrap import dedent
from cloudinit import subp, util
@@ -21,7 +22,6 @@ from cloudinit.settings import PER_INSTANCE
# Define the commands to use
SFDISK_CMD = subp.which("sfdisk")
-SGDISK_CMD = subp.which("sgdisk")
LSBLK_CMD = subp.which("lsblk")
BLKID_CMD = subp.which("blkid")
BLKDEV_CMD = subp.which("blockdev")
@@ -856,44 +856,32 @@ sgdisk_to_gpt_id = {
gpt_id_to_sgdisk = {v: k for k, v in reversed(sgdisk_to_gpt_id.items())}
def check_partition_gpt_layout(device, layout):
- prt_cmd = [SGDISK_CMD, "-p", device]
+ # Use sfdisk's JSON output for reliability
+ prt_cmd = [SFDISK_CMD, "-l", "-J", device]
try:
out, _err = subp.subp(prt_cmd, update_env=LANG_C_ENV)
+ ptable = json.loads(out)["partitiontable"]
+ if "partitions" in ptable:
+ partitions = ptable["partitions"]
+ else:
+ partitions = []
+
except Exception as e:
raise RuntimeError(
"Error running partition command on %s\n%s" % (device, e)
) from e
- out_lines = iter(out.splitlines())
- # Skip header. Output looks like:
- # ***************************************************************
- # Found invalid GPT and valid MBR; converting MBR to GPT format
- # in memory.
- # ***************************************************************
- #
- # Disk /dev/vdb: 83886080 sectors, 40.0 GiB
- # Logical sector size: 512 bytes
- # Disk identifier (GUID): 8A7F11AD-3953-491B-8051-077E01C8E9A7
- # Partition table holds up to 128 entries
- # First usable sector is 34, last usable sector is 83886046
- # Partitions will be aligned on 2048-sector boundaries
- # Total free space is 83476413 sectors (39.8 GiB)
- #
- # Number Start (sector) End (sector) Size Code Name
- # 1 2048 206847 100.0 MiB 0700 Microsoft basic data
- for line in out_lines:
- if line.strip().startswith("Number"):
- break
-
- codes = [line.strip().split()[5] for line in out_lines]
- cleaned = []
-
- # user would expect a code '83' to be Linux, but sgdisk outputs 8300.
- for code in codes:
- if len(code) == 4 and code.endswith("00"):
- code = code[0:2]
- cleaned.append(code)
- return cleaned
+ found_layout = []
+ for part in partitions:
+ if part["type"] in gpt_id_to_sgdisk:
+ ptype = gpt_id_to_sgdisk[part["type"]]
+ if len(ptype) == 4 and ptype[-2:] == "00":
+ ptype = ptype[0:2]
+ found_layout.append(ptype)
+ else:
+ # Unknown GPT UUID, using standard Linux
+ found_layout.append("83")
+ return found_layout
def check_partition_layout(table_type, device, layout):
@@ -1066,11 +1054,11 @@ def get_partition_layout(table_type, size, layout):
This is a future proofing function. To add support for
other layouts, simply add a "get_partition_%s_layout"
function.
+
+ RHEL-only: sfdisk is used both for GPT and MBR
"""
- if "mbr" == table_type:
+ if table_type in ["gpt", "mbr"]:
return get_partition_mbr_layout(size, layout)
- elif "gpt" == table_type:
- return get_partition_gpt_layout(size, layout)
raise RuntimeError("Unable to determine table type")
@@ -1110,28 +1098,26 @@ def exec_mkpart_mbr(device, layout):
def exec_mkpart_gpt(device, layout):
+ prt_cmd = [SFDISK_CMD, "-X", "gpt", "--force", device]
try:
- subp.subp([SGDISK_CMD, "-Z", device])
- for index, (partition_type, (start, end)) in enumerate(layout):
- index += 1
- subp.subp(
- [
- SGDISK_CMD,
- "-n",
- "{}:{}:{}".format(index, start, end),
- device,
- ]
- )
- if partition_type is not None:
- # convert to a 4 char (or more) string right padded with 0
- # 82 -> 8200. 'Linux' -> 'Linux'
- pinput = str(partition_type).ljust(4, "0")
- subp.subp(
- [SGDISK_CMD, "-t", "{}:{}".format(index, pinput), device]
- )
- except Exception:
- LOG.warning("Failed to partition device %s", device)
- raise
+ layout_fixed = []
+ # convert partition UUIDs to GPT UUIDs
+ for part in layout.split('\n'):
+ (pstart, psize, ptype) = part.split(',')
+ if len(ptype) == 2:
+ ptype = ptype + "00"
+ if ptype.upper() in sgdisk_to_gpt_id:
+ ptype = sgdisk_to_gpt_id[ptype]
+ else:
+ # Use standard Linux for unknown ids
+ ptype = "0FC63DAF-8483-4772-8E79-3D69D8477DE4"
+ layout_fixed.append(','.join([pstart, psize, ptype]))
+ layout = '\n'.join(layout_fixed)
+ subp.subp(prt_cmd, data="%s\n" % layout)
+ except Exception as e:
+ raise RuntimeError(
+ "Failed to partition device %s\n%s" % (device, e)
+ ) from e
read_parttbl(device)
--
2.39.3