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:
parent
1c63aee915
commit
5c399d6b43
|
|
@ -111,6 +111,10 @@ $ podman run \
|
||||||
Internally, crun-vm generates a VM image from the bootable container and then
|
Internally, crun-vm generates a VM image from the bootable container and then
|
||||||
boots it.
|
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
|
## First-boot customization
|
||||||
|
|
||||||
### cloud-init
|
### cloud-init
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ engine=$1
|
||||||
container_id=$2
|
container_id=$2
|
||||||
original_root=$3
|
original_root=$3
|
||||||
priv_dir=$4
|
priv_dir=$4
|
||||||
|
disk_size=$5
|
||||||
|
|
||||||
__step() {
|
__step() {
|
||||||
printf "\033[36m%s\033[0m\n" "$*"
|
printf "\033[36m%s\033[0m\n" "$*"
|
||||||
|
|
@ -79,7 +80,20 @@ else
|
||||||
|
|
||||||
# run bootc-install under krun
|
# 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
|
trap 'krun delete --force "$container_name" >/dev/null 2>&1 || true' EXIT
|
||||||
krun run --config "$bootc_dir/config.json" "$container_name" </dev/ptmx
|
krun run --config "$bootc_dir/config.json" "$container_name" </dev/ptmx
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,9 @@ pub struct CustomOptions {
|
||||||
#[clap(long, help = "Use system emulation rather than KVM")]
|
#[clap(long, help = "Use system emulation rather than KVM")]
|
||||||
pub emulated: bool,
|
pub emulated: bool,
|
||||||
|
|
||||||
|
#[clap(long)]
|
||||||
|
pub bootc_disk_size: Option<String>,
|
||||||
|
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub cloud_init: Option<Utf8PathBuf>,
|
pub cloud_init: Option<Utf8PathBuf>,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,9 @@ use std::process::{Command, Stdio};
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, ensure, Context, Result};
|
use anyhow::{anyhow, bail, ensure, Context, Result};
|
||||||
use camino::{Utf8Path, Utf8PathBuf};
|
use camino::{Utf8Path, Utf8PathBuf};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use nix::sys::stat::{major, makedev, minor, mknod, Mode, SFlag};
|
use nix::sys::stat::{major, makedev, minor, mknod, Mode, SFlag};
|
||||||
|
use regex::Regex;
|
||||||
use rust_embed::RustEmbed;
|
use rust_embed::RustEmbed;
|
||||||
|
|
||||||
use crate::commands::create::custom_opts::CustomOptions;
|
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 engine = Engine::detect(&args.container_id, bundle_path, &spec, &original_root_path)?;
|
||||||
let custom_options = CustomOptions::from_spec(&spec, engine)?;
|
let custom_options = CustomOptions::from_spec(&spec, engine)?;
|
||||||
let is_bootc_container = is_bootc_container(&original_root_path, engine)?;
|
let is_bootc_container = is_bootc_container(&original_root_path, &custom_options, engine)?;
|
||||||
|
|
||||||
ensure!(
|
|
||||||
!is_bootc_container || !custom_options.emulated,
|
|
||||||
"--emulated is incompatible with bootable containers"
|
|
||||||
);
|
|
||||||
|
|
||||||
// We include container_id in our paths to ensure no overlap with the user container's contents.
|
// 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));
|
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(&args.container_id)
|
||||||
.arg(&original_root_path)
|
.arg(&original_root_path)
|
||||||
.arg(&priv_dir_path)
|
.arg(&priv_dir_path)
|
||||||
|
.arg(custom_options.bootc_disk_size.unwrap_or_default())
|
||||||
.stdin(Stdio::null())
|
.stdin(Stdio::null())
|
||||||
.stdout(Stdio::null())
|
.stdout(Stdio::null())
|
||||||
.stderr(Stdio::null())
|
.stderr(Stdio::null())
|
||||||
|
|
@ -152,7 +150,11 @@ fn ensure_unprivileged(spec: &oci_spec::runtime::Spec) -> Result<()> {
|
||||||
Ok(())
|
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();
|
let is_bootc_container = original_root_path.join("usr/lib/bootc/install").is_dir();
|
||||||
|
|
||||||
ensure!(
|
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"
|
"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)
|
Ok(is_bootc_container)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue