cloud-init-dev team mailing list archive
-
cloud-init-dev team
-
Mailing list archive
-
Message #02323
[Merge] ~smoser/cloud-init:bug/1692093-sometimes-need-settle into cloud-init:master
Scott Moser has proposed merging ~smoser/cloud-init:bug/1692093-sometimes-need-settle into cloud-init:master.
Commit message:
disk_setup: udev settle before attempting partitioning or fs creation.
This attempts to use udevadm settle to wait until devices have been
fully "realized". If a device exists, there may still be events in
the udev queue that would create its partition table entries.
We need to wait until those have been processed also.
LP: #1692093
Requested reviews:
Paul Meyer (paul-meyer)
cloud-init commiters (cloud-init-dev)
Related bugs:
Bug #1692093 in cloud-init: "Cloud init is re-executing fs and disk setup during reboot"
https://bugs.launchpad.net/cloud-init/+bug/1692093
For more details, see:
https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/324639
--
Your team cloud-init commiters is requested to review the proposed merge of ~smoser/cloud-init:bug/1692093-sometimes-need-settle into cloud-init:master.
diff --git a/cloudinit/config/cc_disk_setup.py b/cloudinit/config/cc_disk_setup.py
index e1505b3..adde1df 100644
--- a/cloudinit/config/cc_disk_setup.py
+++ b/cloudinit/config/cc_disk_setup.py
@@ -680,14 +680,14 @@ def read_parttbl(device):
reliable way to probe the partition table.
"""
blkdev_cmd = [BLKDEV_CMD, '--rereadpt', device]
- udev_cmd = [UDEVADM_CMD, 'settle']
+ udevadm_settle()
try:
- util.subp(udev_cmd)
util.subp(blkdev_cmd)
- util.subp(udev_cmd)
except Exception as e:
util.logexc(LOG, "Failed reading the partition table %s" % e)
+ udevadm_settle()
+
def exec_mkpart_mbr(device, layout):
"""
@@ -737,6 +737,32 @@ def exec_mkpart(table_type, device, layout):
return get_dyn_func("exec_mkpart_%s", table_type, device, layout)
+def udevadm_settle():
+ util.subp(['udevadm', 'settle'])
+
+
+def assert_and_settle_device(device):
+ """Assert that device exists and settle so it is fully recognized."""
+ if not os.path.exists(device):
+ udevadm_settle()
+ if not os.path.exists(device):
+ raise RuntimeError("Device %s did not exist and was not created "
+ "with a udevamd settle." % device)
+
+ # The device existed, so lets make sure all its partitions
+ # are created and udev entries read by lsblk updated.
+ blkdev_cmd = [BLKDEV_CMD, '--rereadpt', device]
+ try:
+ util.subp(blkdev_cmd)
+ except util.ProcessExecutionError as e:
+ # this can fail legitimately if the device is busy.
+ # its possibly busy even as a result of udev events.
+ LOG.debug("Running blockdev --rereadpt failed (not necessarily "
+ "significant): %s", e)
+
+ udevadm_settle()
+
+
def mkpart(device, definition):
"""
Creates the partition table.
@@ -752,6 +778,7 @@ def mkpart(device, definition):
device: the device to work on.
"""
# ensure that we get a real device rather than a symbolic link
+ assert_and_settle_device(device)
device = os.path.realpath(device)
LOG.debug("Checking values for %s definition", device)
@@ -852,6 +879,7 @@ def mkfs(fs_cfg):
overwrite = fs_cfg.get('overwrite', False)
# ensure that we get a real device rather than a symbolic link
+ assert_and_settle_device(device)
device = os.path.realpath(device)
# This allows you to define the default ephemeral or swap
References