From 9fa139511eb90119a3206fd9c7a6fbc3866e5e79 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Thu, 22 Dec 2022 17:15:55 +1300 Subject: [PATCH] Check and grow the GPT structure to the end of the volume In the baremetal case this isn't required because it is done by ironic-python-agent when writing the image to the volume[1]. But when using the image directly (such as in a nova VM) the GPT structure needs to be extended first. This change does that, along with the detection for whether extending is required, using the same approach as [1]. [1] https://github.com/openstack/ironic-lib/blob/master/ironic_lib/disk_utils.py#L670-L674 Co-Authored-By: rminishev@itkey.com Co-Authored-By: sbaker@redhat.com Change-Id: I3240eb0ef4dbbb41557985f0129ae4998a846417 --- .../growvols/static/usr/local/sbin/growvols | 13 ++++++++++++ .../elements/growvols/tests/test_growvols.py | 21 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/diskimage_builder/elements/growvols/static/usr/local/sbin/growvols b/diskimage_builder/elements/growvols/static/usr/local/sbin/growvols index 0c3fdc0b..8894bed4 100755 --- a/diskimage_builder/elements/growvols/static/usr/local/sbin/growvols +++ b/diskimage_builder/elements/growvols/static/usr/local/sbin/growvols @@ -269,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 @@ -490,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) diff --git a/diskimage_builder/elements/growvols/tests/test_growvols.py b/diskimage_builder/elements/growvols/tests/test_growvols.py index b1622d64..e45c652a 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" @@ -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,6 +598,7 @@ class TestGrowvols(base.BaseTestCase): mock_execute.reset_mock() mock_execute.side_effect = [ LSBLK, + '', SGDISK_LARGEST, VGS, LVS_THIN, @@ -589,6 +609,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']),