100 lines
3.1 KiB
Diff
100 lines
3.1 KiB
Diff
From 598e0560d64f949369962ebbce2c53207763f5d2 Mon Sep 17 00:00:00 2001
|
|
From: Brett Holman <brett.holman@canonical.com>
|
|
Date: Fri, 5 Jan 2024 13:10:01 -0700
|
|
Subject: [PATCH] fix: fix growpart race (#4618)
|
|
|
|
Fixes GH-4613
|
|
---
|
|
cloudinit/config/cc_growpart.py | 23 +++++++++++++++++-----
|
|
tests/unittests/config/test_cc_growpart.py | 16 +++++++++++++++
|
|
2 files changed, 34 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/cloudinit/config/cc_growpart.py b/cloudinit/config/cc_growpart.py
|
|
index f2e847e..f00e2e9 100644
|
|
--- a/cloudinit/config/cc_growpart.py
|
|
+++ b/cloudinit/config/cc_growpart.py
|
|
@@ -19,7 +19,7 @@ from abc import ABC, abstractmethod
|
|
from contextlib import suppress
|
|
from pathlib import Path
|
|
from textwrap import dedent
|
|
-from typing import Tuple
|
|
+from typing import Optional, Tuple
|
|
|
|
from cloudinit import subp, temp_utils, util
|
|
from cloudinit.cloud import Cloud
|
|
@@ -283,12 +283,16 @@ class ResizeGpart(Resizer):
|
|
return (before, get_size(partdev))
|
|
|
|
|
|
-def get_size(filename):
|
|
- fd = os.open(filename, os.O_RDONLY)
|
|
+def get_size(filename) -> Optional[int]:
|
|
+ fd = None
|
|
try:
|
|
+ fd = os.open(filename, os.O_RDONLY)
|
|
return os.lseek(fd, 0, os.SEEK_END)
|
|
+ except FileNotFoundError:
|
|
+ return None
|
|
finally:
|
|
- os.close(fd)
|
|
+ if fd:
|
|
+ os.close(fd)
|
|
|
|
|
|
def device_part_info(devpath):
|
|
@@ -571,7 +575,7 @@ def resize_devices(resizer, devices):
|
|
continue
|
|
|
|
try:
|
|
- (old, new) = resizer.resize(disk, ptnum, blockdev)
|
|
+ old, new = resizer.resize(disk, ptnum, blockdev)
|
|
if old == new:
|
|
info.append(
|
|
(
|
|
@@ -580,6 +584,15 @@ def resize_devices(resizer, devices):
|
|
"no change necessary (%s, %s)" % (disk, ptnum),
|
|
)
|
|
)
|
|
+ elif new is None or old is None:
|
|
+ info.append(
|
|
+ (
|
|
+ devent,
|
|
+ RESIZE.CHANGED,
|
|
+ "changed (%s, %s) size, new size is unknown"
|
|
+ % (disk, ptnum),
|
|
+ )
|
|
+ )
|
|
else:
|
|
info.append(
|
|
(
|
|
diff --git a/tests/unittests/config/test_cc_growpart.py b/tests/unittests/config/test_cc_growpart.py
|
|
index 5b97f7b..85a4759 100644
|
|
--- a/tests/unittests/config/test_cc_growpart.py
|
|
+++ b/tests/unittests/config/test_cc_growpart.py
|
|
@@ -389,6 +389,22 @@ class TestResize(unittest.TestCase):
|
|
os.stat = real_stat
|
|
|
|
|
|
+class TestGetSize:
|
|
+ @pytest.mark.parametrize(
|
|
+ "file_exists, expected",
|
|
+ (
|
|
+ (False, None),
|
|
+ (True, 1),
|
|
+ ),
|
|
+ )
|
|
+ def test_get_size_behaves(self, file_exists, expected, tmp_path):
|
|
+ """Ensure that get_size() doesn't raise exception"""
|
|
+ tmp_file = tmp_path / "tmp.txt"
|
|
+ if file_exists:
|
|
+ tmp_file.write_bytes(b"0")
|
|
+ assert expected == cc_growpart.get_size(tmp_file)
|
|
+
|
|
+
|
|
class TestEncrypted:
|
|
"""Attempt end-to-end scenarios using encrypted devices.
|
|
|
|
--
|
|
2.27.0
|
|
|