176 lines
6.2 KiB
Diff
176 lines
6.2 KiB
Diff
|
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
|
||
|
|