Skip to content

Commit

Permalink
[WIP] Check for log device before starting migration
Browse files Browse the repository at this point in the history
Signed-off-by: Leandro Motta Barros <[email protected]>
Change-type: minor
  • Loading branch information
lmbarros committed May 2, 2024
1 parent e96d4b5 commit a779c71
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 42 deletions.
110 changes: 69 additions & 41 deletions src/stage1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,12 +398,7 @@ fn prepare(opts: &Options, mig_info: &mut MigrateInfo) -> Result<()> {
let new_init_path = path_append(&takeover_dir, format!("/bin/{}", env!("CARGO_PKG_NAME")));
// Assets::write_stage2_script(&takeover_dir, &new_init_path, &tty, opts.get_s2_log_level())?;

let block_dev_info = if get_os_name()?.starts_with(BALENA_OS_NAME) {
// can't use default root dir due to overlayfs
BlockDeviceInfo::new_for_dir(BALENA_DATA_MP)?
} else {
BlockDeviceInfo::new()?
};
let block_dev_info = get_block_dev_info()?;

let flash_dev = if let Some(flash_dev) = opts.flash_to() {
if let Some(flash_dev) = block_dev_info.get_devices().get(flash_dev) {
Expand Down Expand Up @@ -431,41 +426,7 @@ fn prepare(opts: &Options, mig_info: &mut MigrateInfo) -> Result<()> {
));
}

let log_device = if let Some(log_dev_path) = opts.log_to() {
if let Some(log_dev) = block_dev_info.get_devices().get(log_dev_path) {
if let Some(partition_info) = log_dev.get_partition_info() {
if let Some(fs_type) = partition_info.fs_type() {
const SUPPORTED_LOG_FS_TYPES: [&str; 3] = ["vfat", "ext3", "ext4"];
if SUPPORTED_LOG_FS_TYPES.iter().any(|val| *val == fs_type) {
Some(LogDevice {
dev_name: log_dev_path.clone(),
fs_type: fs_type.to_owned(),
})
} else {
warn!("The log device's ('{}') files system type '{}' is not in the list of supported file systems: {:?}. Your device will not be able to write stage2 logs",
log_dev_path.display(),
fs_type,
SUPPORTED_LOG_FS_TYPES);
None
}
} else {
warn!("We could not detect the filesystemm type for the log device '{}'. Your device will not be able to write stage2 logs",
log_dev_path.display());
None
}
} else {
warn!("The log device '{}' is not a partition. Your device will not be able to write stage2 logs",
log_dev_path.display());
None
}
} else {
warn!("The log device '{}' could not be found. Your device will not be able to write stage2 logs",
log_dev_path.display());
None
}
} else {
None
};
let log_device = get_log_device(opts, &block_dev_info);

// collect partitions that need to be unmounted

Expand Down Expand Up @@ -547,6 +508,73 @@ fn prepare(opts: &Options, mig_info: &mut MigrateInfo) -> Result<()> {
Ok(())
}

/// Returns information about the block devices on the system.
fn get_block_dev_info() -> Result<BlockDeviceInfo> {
let block_dev_info = if get_os_name()?.starts_with(BALENA_OS_NAME) {
// can't use default root dir due to overlayfs
BlockDeviceInfo::new_for_dir(BALENA_DATA_MP)?
} else {
BlockDeviceInfo::new()?
};
Ok(block_dev_info)
}

/// Gets the log device to use for stage 2 logs. Returns `None` if the user
/// didn't request a log device, or if the requested log device is not usable.
/// If the log device is not usable, an error message is logged.
fn get_log_device(opts: &Options, block_dev_info: &BlockDeviceInfo) -> Option<LogDevice> {
let log_dev_path = if let Some(path) = opts.log_to() {
path
} else {
info!("No stage 2 log device requested");
return None;
};

let log_dev = if let Some(dev) = block_dev_info.get_devices().get(log_dev_path) {
dev
} else {
error!(
"The log device '{}' could not be found, so it can't be used for stage 2 logs",
log_dev_path.display()
);
return None;
};

let partition_info = if let Some(partition_info) = log_dev.get_partition_info() {
partition_info
} else {
error!(
"The log device '{}' is not a partition, so it can't be used for stage 2 logs",
log_dev_path.display()
);
return None;
};

let fs_type = if let Some(fs_type) = partition_info.fs_type() {
fs_type
} else {
error!(
"We could not detect the filesystem type for the log device '{}', so it can't be used for stage 2 logs",
log_dev_path.display()
);
return None;
};

const SUPPORTED_LOG_FS_TYPES: [&str; 3] = ["vfat", "ext3", "ext4"];
if !SUPPORTED_LOG_FS_TYPES.contains(&fs_type) {
error!("The log device's ('{}') files system type '{}' is not one of the supported file systems: {:?}. It can't be used for stage 2 logs",
log_dev_path.display(),
fs_type,
SUPPORTED_LOG_FS_TYPES);
return None;
}

Some(LogDevice {
dev_name: log_dev_path.clone(),
fs_type: fs_type.to_owned(),
})
}

pub fn stage1(opts: &Options) -> Result<()> {
Logger::set_default_level(opts.log_level());
Logger::set_brief_info(true);
Expand Down
23 changes: 22 additions & 1 deletion src/stage1/checks.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,36 @@
use log::error;

use super::{block_device_info::BlockDeviceInfo, get_block_dev_info, get_log_device};
use crate::common::{is_admin, Error, Options, Result};

/// Performs checks to ensure that the program can run properly with the
/// provided command-line options. Returns an error if the program cannot run
/// for some reason.
pub(crate) fn do_early_checks(_opts: &Options) -> Result<()> {
pub(crate) fn do_early_checks(opts: &Options) -> Result<()> {
if !is_admin()? {
error!("please run this program as root");
return Err(Error::displayed());
}

let block_dev_info = get_block_dev_info()?;

if !check_log_device(opts, &block_dev_info) {
error!("the requested log device is not suitable for writing stage2 logs");
return Err(Error::displayed());
}

Ok(())
}

/// Checks if the log device requested with `--log-device` is suitable for
/// writing stage2 logs.
fn check_log_device(opts: &Options, block_dev_info: &BlockDeviceInfo) -> bool {
if opts.log_to().is_none() {
// No log device requested: that's fine!
return true;
};

// But if the user requested a log device, we must be able to get it. If we
// can't, *that* is a problem!
get_log_device(opts, block_dev_info).is_some()
}

0 comments on commit a779c71

Please sign in to comment.