mirror of
https://github.com/philmmanjaro/alma.git
synced 2025-12-06 19:29:21 +01:00
Refactor main.rs and fix clippy lints
Status: WIP Completed: * Fixed flagged clippy lints * Moved qemu(), main.rs::mount() and chroot() to the tools module. * Moved constants in main.rs to constants.rs (including base packages array) * Renamed Presets struct to PresetsCollection to avoid confusion with Preset struct * Moved main() to the top of main.rs to highlight general logic path * Added comments and docstrings to some functions * Removed some uses of `use foo::*` to make the source of imported functions and structs clearer TODO: * Move remaining code in main.rs to modules (except main()) * Break up create() function in to separate steps * Log every command run (with arguments) to debug! when verbose flag is used * Add docstrings for remaining functions and document constants (e.g. why noatime is used) * Remove remaining uses of `use foo::*` * Consider renaming/moving tools module to address tool:: vs. Tool:: confusion
This commit is contained in:
70
src/tool/chroot.rs
Normal file
70
src/tool/chroot.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
use super::mount;
|
||||
use super::Tool;
|
||||
use crate::args;
|
||||
use crate::constants::{BOOT_PARTITION_INDEX, ROOT_PARTITION_INDEX};
|
||||
use crate::error::{Error, ErrorKind};
|
||||
use crate::process::CommandExt;
|
||||
use crate::storage;
|
||||
use crate::storage::{is_encrypted_device, EncryptedDevice};
|
||||
use crate::storage::{BlockDevice, Filesystem, FilesystemType, LoopDevice};
|
||||
use log::info;
|
||||
|
||||
use failure::ResultExt;
|
||||
use tempfile::tempdir;
|
||||
|
||||
/// Use arch-chroot to chroot to the given device
|
||||
/// Also handles encrypted root partitions (detected by checking for the LUKS magic header)
|
||||
pub fn chroot(command: args::ChrootCommand) -> Result<(), Error> {
|
||||
let arch_chroot = Tool::find("arch-chroot")?;
|
||||
let cryptsetup;
|
||||
|
||||
let loop_device: Option<LoopDevice>;
|
||||
let storage_device =
|
||||
match storage::StorageDevice::from_path(&command.block_device, command.allow_non_removable)
|
||||
{
|
||||
Ok(b) => b,
|
||||
Err(_) => {
|
||||
loop_device = Some(LoopDevice::create(&command.block_device)?);
|
||||
storage::StorageDevice::from_path(
|
||||
loop_device.as_ref().unwrap().path(),
|
||||
command.allow_non_removable,
|
||||
)?
|
||||
}
|
||||
};
|
||||
let mount_point = tempdir().context(ErrorKind::TmpDirError)?;
|
||||
|
||||
let boot_partition = storage_device.get_partition(BOOT_PARTITION_INDEX)?;
|
||||
let boot_filesystem = Filesystem::from_partition(&boot_partition, FilesystemType::Vfat);
|
||||
|
||||
let root_partition_base = storage_device.get_partition(ROOT_PARTITION_INDEX)?;
|
||||
let encrypted_root = if is_encrypted_device(&root_partition_base)? {
|
||||
cryptsetup = Some(Tool::find("cryptsetup")?);
|
||||
Some(EncryptedDevice::open(
|
||||
cryptsetup.as_ref().unwrap(),
|
||||
&root_partition_base,
|
||||
"alma_root".into(),
|
||||
)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let root_partition = if let Some(e) = encrypted_root.as_ref() {
|
||||
e as &dyn BlockDevice
|
||||
} else {
|
||||
&root_partition_base as &dyn BlockDevice
|
||||
};
|
||||
let root_filesystem = Filesystem::from_partition(root_partition, FilesystemType::Ext4);
|
||||
|
||||
let mount_stack = mount(mount_point.path(), &boot_filesystem, &root_filesystem)?;
|
||||
|
||||
arch_chroot
|
||||
.execute()
|
||||
.arg(mount_point.path())
|
||||
.args(&command.command)
|
||||
.run(ErrorKind::Interactive)?;
|
||||
|
||||
info!("Unmounting filesystems");
|
||||
mount_stack.umount()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
30
src/tool/mod.rs
Normal file
30
src/tool/mod.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
mod chroot;
|
||||
mod mount;
|
||||
mod qemu;
|
||||
|
||||
pub use chroot::chroot;
|
||||
pub use mount::mount;
|
||||
pub use qemu::qemu;
|
||||
|
||||
use crate::error::*;
|
||||
use failure::ResultExt;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use which::which;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Tool {
|
||||
exec: PathBuf,
|
||||
}
|
||||
|
||||
impl Tool {
|
||||
pub fn find(name: &'static str) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
exec: which(name).context(ErrorKind::NoTool(name))?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn execute(&self) -> Command {
|
||||
Command::new(&self.exec)
|
||||
}
|
||||
}
|
||||
37
src/tool/mount.rs
Normal file
37
src/tool/mount.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
use crate::error::{Error, ErrorKind};
|
||||
use crate::storage::{Filesystem, MountStack};
|
||||
use failure::ResultExt;
|
||||
use log::{debug, info};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
/// Mounts root filesystem to given mount_path
|
||||
/// Mounts boot filesystem to mount_path/boot
|
||||
/// Note we mount with noatime to reduce disk writes by not recording file access times
|
||||
pub fn mount<'a>(
|
||||
mount_path: &Path,
|
||||
boot_filesystem: &'a Filesystem,
|
||||
root_filesystem: &'a Filesystem,
|
||||
) -> Result<MountStack<'a>, Error> {
|
||||
let mut mount_stack = MountStack::new();
|
||||
debug!(
|
||||
"Root partition: {}",
|
||||
root_filesystem.block().path().display()
|
||||
);
|
||||
|
||||
info!("Mounting filesystems to {}", mount_path.display());
|
||||
mount_stack
|
||||
.mount(&root_filesystem, mount_path.into(), None)
|
||||
.context(ErrorKind::Mounting)?;
|
||||
|
||||
let boot_point = mount_path.join("boot");
|
||||
if !boot_point.exists() {
|
||||
fs::create_dir(&boot_point).context(ErrorKind::CreateBoot)?;
|
||||
}
|
||||
|
||||
mount_stack
|
||||
.mount(&boot_filesystem, boot_point, None)
|
||||
.context(ErrorKind::Mounting)?;
|
||||
|
||||
Ok(mount_stack)
|
||||
}
|
||||
43
src/tool/qemu.rs
Normal file
43
src/tool/qemu.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
use super::Tool;
|
||||
use crate::args;
|
||||
use crate::error;
|
||||
use log::debug;
|
||||
|
||||
use failure::ResultExt;
|
||||
use std::os::unix::process::CommandExt as UnixCommandExt;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Loads given block device in qemu
|
||||
/// Uses kvm if it is enabled
|
||||
pub fn qemu(command: args::QemuCommand) -> Result<(), error::Error> {
|
||||
let qemu = Tool::find("qemu-system-x86_64")?;
|
||||
|
||||
let mut run = qemu.execute();
|
||||
run.args(&[
|
||||
"-m",
|
||||
"4G",
|
||||
"-netdev",
|
||||
"user,id=user.0",
|
||||
"-device",
|
||||
"virtio-net-pci,netdev=user.0",
|
||||
"-device",
|
||||
"qemu-xhci,id=xhci",
|
||||
"-device",
|
||||
"usb-tablet,bus=xhci.0",
|
||||
"-drive",
|
||||
])
|
||||
.arg(format!(
|
||||
"file={},if=virtio,format=raw",
|
||||
command.block_device.display()
|
||||
))
|
||||
.args(command.args);
|
||||
|
||||
if PathBuf::from("/dev/kvm").exists() {
|
||||
debug!("KVM is enabled");
|
||||
run.args(&["-enable-kvm", "-cpu", "host"]);
|
||||
}
|
||||
|
||||
let err = run.exec();
|
||||
|
||||
Err(err).context(error::ErrorKind::Qemu)?
|
||||
}
|
||||
Reference in New Issue
Block a user