Add --bootc-disk-size option

It allows settings the disk size of the VM image that is generated from
a bootc container image.

Also improve the default disk size by basing it on the container image
size.

Signed-off-by: Alberto Faria <afaria@redhat.com>
This commit is contained in:
Alberto Faria 2024-04-28 13:46:16 +01:00
parent 1c63aee915
commit 5c399d6b43
5 changed files with 79 additions and 8 deletions

View File

@ -111,6 +111,10 @@ $ podman run \
Internally, crun-vm generates a VM image from the bootable container and then
boots it.
By default, the VM image is given a disk size roughly double the size of the
bootc container image. To change this, use the `--bootc-disk-size <size>[KMGT]`
option.
## First-boot customization
### cloud-init

View File

@ -7,6 +7,7 @@ engine=$1
container_id=$2
original_root=$3
priv_dir=$4
disk_size=$5
__step() {
printf "\033[36m%s\033[0m\n" "$*"
@ -79,7 +80,20 @@ else
# run bootc-install under krun
truncate --size 10G "$bootc_dir/image.raw" # TODO: allow adjusting disk size
if [[ -z "$disk_size" ]]; then
container_image_size=$(
"$engine" image inspect --format '{{.VirtualSize}}' "$image_id"
)
# use double the container image size to allow for in-place updates
disk_size=$(( container_image_size * 2 ))
# round up to 1 MiB
alignment=$(( 2**20 ))
disk_size=$(( (disk_size + alignment - 1) / alignment * alignment ))
fi
truncate --size "$disk_size" "$bootc_dir/image.raw"
trap 'krun delete --force "$container_name" >/dev/null 2>&1 || true' EXIT
krun run --config "$bootc_dir/config.json" "$container_name" </dev/ptmx

View File

@ -55,6 +55,9 @@ pub struct CustomOptions {
#[clap(long, help = "Use system emulation rather than KVM")]
pub emulated: bool,
#[clap(long)]
pub bootc_disk_size: Option<String>,
#[clap(long)]
pub cloud_init: Option<Utf8PathBuf>,

View File

@ -14,7 +14,9 @@ use std::process::{Command, Stdio};
use anyhow::{anyhow, bail, ensure, Context, Result};
use camino::{Utf8Path, Utf8PathBuf};
use lazy_static::lazy_static;
use nix::sys::stat::{major, makedev, minor, mknod, Mode, SFlag};
use regex::Regex;
use rust_embed::RustEmbed;
use crate::commands::create::custom_opts::CustomOptions;
@ -38,12 +40,7 @@ pub fn create(args: &liboci_cli::Create, raw_args: &[impl AsRef<OsStr>]) -> Resu
let engine = Engine::detect(&args.container_id, bundle_path, &spec, &original_root_path)?;
let custom_options = CustomOptions::from_spec(&spec, engine)?;
let is_bootc_container = is_bootc_container(&original_root_path, engine)?;
ensure!(
!is_bootc_container || !custom_options.emulated,
"--emulated is incompatible with bootable containers"
);
let is_bootc_container = is_bootc_container(&original_root_path, &custom_options, engine)?;
// We include container_id in our paths to ensure no overlap with the user container's contents.
let priv_dir_path = original_root_path.join(format!("crun-vm-{}", args.container_id));
@ -121,6 +118,7 @@ pub fn create(args: &liboci_cli::Create, raw_args: &[impl AsRef<OsStr>]) -> Resu
.arg(&args.container_id)
.arg(&original_root_path)
.arg(&priv_dir_path)
.arg(custom_options.bootc_disk_size.unwrap_or_default())
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
@ -152,7 +150,11 @@ fn ensure_unprivileged(spec: &oci_spec::runtime::Spec) -> Result<()> {
Ok(())
}
fn is_bootc_container(original_root_path: &Utf8Path, engine: Engine) -> Result<bool> {
fn is_bootc_container(
original_root_path: &Utf8Path,
custom_options: &CustomOptions,
engine: Engine,
) -> Result<bool> {
let is_bootc_container = original_root_path.join("usr/lib/bootc/install").is_dir();
ensure!(
@ -160,6 +162,31 @@ fn is_bootc_container(original_root_path: &Utf8Path, engine: Engine) -> Result<b
"bootc containers are only supported with Podman and Docker"
);
ensure!(
!is_bootc_container || !custom_options.emulated,
"--emulated is incompatible with bootable containers"
);
if let Some(size) = &custom_options.bootc_disk_size {
lazy_static! {
static ref SIZE_PATTERN: Regex = Regex::new(r"^[0-9]+[KMGT]?$").unwrap();
}
ensure!(
SIZE_PATTERN.is_match(size),
concat!(
"--bootc-disk-size value must be a number followed by an optional suffix K",
" (kilobyte, 1024), M (megabyte, 1024k), G (gigabyte, 1024M), or T (terabyte,",
" 1024G)",
)
);
ensure!(
is_bootc_container,
"--bootc-disk-size only applies to bootable containers"
);
}
Ok(is_bootc_container)
}

View File

@ -0,0 +1,23 @@
# SPDX-License-Identifier: GPL-2.0-or-later
image="${TEST_IMAGES[fedora-bootc]}"
user="${TEST_IMAGES_DEFAULT_USER[fedora-bootc]}"
__run() {
__engine run --detach --name bootc-disk-size "$image" --bootc-disk-size "$1"
}
! RUST_LIB_BACKTRACE=0 __run 0
__engine rm bootc-disk-size
for size in 1K 1M; do
__run "$size"
! __engine exec bootc-disk-size --as "$user"
__engine rm --force bootc-disk-size
done
for size in 1G 1T 1024T; do
__run "$size"
__engine exec bootc-disk-size --as "$user"
__engine rm --force bootc-disk-size
done