Refactor: block-device partitioning cleanup
Now that the main partitioning refactor patch is merged, there is a small relict of handling partitions still in the disk-image-create main. This patch moves the functionality from disk-image-create to the block-device/partitioning module: it is mostly a rewrite of the original bash code in python. Change-Id: Ia73baeca74180a7bc9ea487da03ff56d6a3070ce Signed-off-by: Andreas Florath <andreas@florath.net>
This commit is contained in:
parent
f1776d72aa
commit
866a06f92d
@ -30,6 +30,47 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class BlockDevice(object):
|
class BlockDevice(object):
|
||||||
|
"""Handles block devices.
|
||||||
|
|
||||||
|
This class handles the complete setup and deletion of all aspects
|
||||||
|
of the block device level.
|
||||||
|
|
||||||
|
A typical call sequence:
|
||||||
|
|
||||||
|
cmd_create: creates all the different aspects of the block
|
||||||
|
device. When this call is successful, the complete block level
|
||||||
|
device is set up, filesystems are created and are mounted at
|
||||||
|
the correct position.
|
||||||
|
After this call it is possible to copy / install all the needed
|
||||||
|
files into the appropriate directories.
|
||||||
|
|
||||||
|
cmd_umount: unmount and detaches all directories and used many
|
||||||
|
resources. After this call the used (e.g.) images are still
|
||||||
|
available for further handling, e.g. converting from raw in
|
||||||
|
some other format.
|
||||||
|
|
||||||
|
cmd_cleanup: removes everything that was created with the
|
||||||
|
'cmd_create' call, i.e. all images files themselves and
|
||||||
|
internal temporary configuration.
|
||||||
|
|
||||||
|
cmd_delete: unmounts and removes everything that was created
|
||||||
|
during the 'cmd_create' all. This call should be used in error
|
||||||
|
conditions when there is the need to remove all allocated
|
||||||
|
resources immediately and as good as possible.
|
||||||
|
From the functional point of view this is mostly the same as a
|
||||||
|
call to 'cmd_umount' and 'cmd_cleanup' - but is typically more
|
||||||
|
error tolerance.
|
||||||
|
|
||||||
|
In a script this should be called in the following way:
|
||||||
|
|
||||||
|
dib-block-device --phase=create ...
|
||||||
|
trap "dib-block-device --phase=delete ..." EXIT
|
||||||
|
# copy / install files
|
||||||
|
dib-block-device --phase=umount ...
|
||||||
|
# convert image(s)
|
||||||
|
dib-block-device --phase=cleanup ...
|
||||||
|
trap - EXIT
|
||||||
|
"""
|
||||||
|
|
||||||
# Default configuration:
|
# Default configuration:
|
||||||
# one image, one partition, mounted under '/'
|
# one image, one partition, mounted under '/'
|
||||||
|
@ -19,6 +19,8 @@ from diskimage_builder.block_device.utils import parse_abs_size_spec
|
|||||||
from diskimage_builder.block_device.utils import parse_rel_size_spec
|
from diskimage_builder.block_device.utils import parse_rel_size_spec
|
||||||
from diskimage_builder.graph.digraph import Digraph
|
from diskimage_builder.graph.digraph import Digraph
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -148,6 +150,51 @@ class Partitioning(object):
|
|||||||
for _, part in self.partitions.items():
|
for _, part in self.partitions.items():
|
||||||
dg.add_node(part)
|
dg.add_node(part)
|
||||||
|
|
||||||
|
def _exec_sudo(self, cmd):
|
||||||
|
sudo_cmd = ["sudo"]
|
||||||
|
sudo_cmd.extend(cmd)
|
||||||
|
logger.info("Calling [%s]" % " ".join(sudo_cmd))
|
||||||
|
subp = subprocess.Popen(sudo_cmd)
|
||||||
|
rval = subp.wait()
|
||||||
|
if rval != 0:
|
||||||
|
logger.error("Calling [%s] failed with [%s]" %
|
||||||
|
(" ".join(sudo_cmd), rval))
|
||||||
|
logger.error("Trying to continue")
|
||||||
|
|
||||||
|
def _all_part_devices_exist(self, expected_part_devices):
|
||||||
|
for part_device in expected_part_devices:
|
||||||
|
logger.debug("Checking if partition device [%s] exists" %
|
||||||
|
part_device)
|
||||||
|
if not os.path.exists(part_device):
|
||||||
|
logger.info("Partition device [%s] does not exists"
|
||||||
|
% part_device)
|
||||||
|
return False
|
||||||
|
logger.debug("Partition already exists [%s]" % part_device)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _notify_os_of_partition_changes(self, device_path, partition_devices):
|
||||||
|
"""Notify of of partition table changes
|
||||||
|
|
||||||
|
There is the need to call some programs to inform the operating
|
||||||
|
system of partition tables changes.
|
||||||
|
These calls are highly distribution and version specific. Here
|
||||||
|
a couple of different methods are used to get the best result.
|
||||||
|
"""
|
||||||
|
self._exec_sudo(["partprobe", device_path])
|
||||||
|
self._exec_sudo(["udevadm", "settle"])
|
||||||
|
|
||||||
|
if self._all_part_devices_exist(partition_devices):
|
||||||
|
return
|
||||||
|
# If running inside Docker, make our nodes manually, because udev
|
||||||
|
# will not be working.
|
||||||
|
if os.path.exists("/.dockerenv"):
|
||||||
|
# kpartx cannot run in sync mode in docker.
|
||||||
|
self._exec_sudo(["kpartx", "-av", device_path])
|
||||||
|
self._exec_sudo(["dmsetup", "--noudevsync", "mknodes"])
|
||||||
|
return
|
||||||
|
|
||||||
|
self._exec_sudo(["kpartx", "-avs", device_path])
|
||||||
|
|
||||||
def create(self, result, rollback):
|
def create(self, result, rollback):
|
||||||
image_path = result[self.base]['image']
|
image_path = result[self.base]['image']
|
||||||
device_path = result[self.base]['device']
|
device_path = result[self.base]['device']
|
||||||
@ -160,6 +207,7 @@ class Partitioning(object):
|
|||||||
|
|
||||||
assert self.label == 'mbr'
|
assert self.label == 'mbr'
|
||||||
|
|
||||||
|
partition_devices = set()
|
||||||
disk_size = self._size_of_block_dev(image_path)
|
disk_size = self._size_of_block_dev(image_path)
|
||||||
with MBR(image_path, disk_size, self.align) as part_impl:
|
with MBR(image_path, disk_size, self.align) as part_impl:
|
||||||
for part_name, part_cfg in self.partitions.items():
|
for part_name, part_cfg in self.partitions.items():
|
||||||
@ -178,7 +226,10 @@ class Partitioning(object):
|
|||||||
part_size, part_type)
|
part_size, part_type)
|
||||||
logger.debug("Create partition [%s] [%d]" %
|
logger.debug("Create partition [%s] [%d]" %
|
||||||
(part_name, part_no))
|
(part_name, part_no))
|
||||||
result[part_name] = {'device': device_path + "p%d" % part_no}
|
partition_device_name = device_path + "p%d" % part_no
|
||||||
|
result[part_name] = {'device': partition_device_name}
|
||||||
|
partition_devices.add(partition_device_name)
|
||||||
|
|
||||||
self.already_created = True
|
self.already_created = True
|
||||||
|
self._notify_os_of_partition_changes(device_path, partition_devices)
|
||||||
return
|
return
|
||||||
|
@ -415,31 +415,6 @@ export EXTRA_DETACH="detach_loopback ${IMAGE_BLOCK_DEVICE_WITHOUT_PART}"
|
|||||||
export EXTRA_UNMOUNT="dib-block-device --phase=cleanup \
|
export EXTRA_UNMOUNT="dib-block-device --phase=cleanup \
|
||||||
--build-dir=\"${TMP_BUILD_DIR}\""
|
--build-dir=\"${TMP_BUILD_DIR}\""
|
||||||
|
|
||||||
# Create the partitions and make them visible to the system
|
|
||||||
|
|
||||||
sudo partprobe $IMAGE_BLOCK_DEVICE_WITHOUT_PART
|
|
||||||
|
|
||||||
# To ensure no race conditions exist from calling partprobe
|
|
||||||
sudo udevadm settle
|
|
||||||
|
|
||||||
# If the partition isn't under /dev/loop*p1, create it with kpartx
|
|
||||||
DM=
|
|
||||||
if [ ! -e "${IMAGE_BLOCK_DEVICE}" ]; then
|
|
||||||
DM=${IMAGE_BLOCK_DEVICE/#\/dev/\/dev\/mapper}
|
|
||||||
# If running inside Docker, make our nodes manually, because udev will not be working.
|
|
||||||
if [ -f /.dockerenv ]; then
|
|
||||||
# kpartx cannot run in sync mode in docker.
|
|
||||||
sudo kpartx -av ${IMAGE_BLOCK_DEVICE_WITHOUT_PART}
|
|
||||||
sudo dmsetup --noudevsync mknodes
|
|
||||||
else
|
|
||||||
sudo kpartx -asv ${IMAGE_BLOCK_DEVICE_WITHOUT_PART}
|
|
||||||
fi
|
|
||||||
elif [[ "$ARCH" =~ "ppc" ]]; then
|
|
||||||
sudo kpartx -asv ${IMAGE_BLOCK_DEVICE_WITHOUT_PART}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# End: Creation of the partitions
|
|
||||||
|
|
||||||
sudo mkfs -t $FS_TYPE $MKFS_OPTS -L ${DIB_ROOT_LABEL} ${IMAGE_BLOCK_DEVICE}
|
sudo mkfs -t $FS_TYPE $MKFS_OPTS -L ${DIB_ROOT_LABEL} ${IMAGE_BLOCK_DEVICE}
|
||||||
# Tuning the rootfs uuid works only for ext filesystems.
|
# Tuning the rootfs uuid works only for ext filesystems.
|
||||||
if echo "$FS_TYPE" | grep -q "^ext"; then
|
if echo "$FS_TYPE" | grep -q "^ext"; then
|
||||||
|
Loading…
Reference in New Issue
Block a user