Compare commits

...
2 Commits
10 changed files with 313 additions and 771 deletions
Generated
+123 -513
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -8,7 +8,7 @@ edition = "2024"
[dependencies] [dependencies]
blocking = "1.6" blocking = "1.6"
iced = { version = "0.14", default-features = false, features = ["crisp", "linux-theme-detection", "tiny-skia", "wgpu", "x11", "smol", "image"] } iced = { version = "0.14", default-features = false, features = ["crisp", "linux-theme-detection", "tiny-skia", "x11", "smol", "image"] }
#iced = { git = "https://github.com/iced-rs/iced", branch = "vello_cpu", default-features = false, features = ["crisp", "linux-theme-detection", "vello-cpu", "x11", "smol", "image"]} #iced = { git = "https://github.com/iced-rs/iced", branch = "vello_cpu", default-features = false, features = ["crisp", "linux-theme-detection", "vello-cpu", "x11", "smol", "image"]}
iced_moving_picture = "0" iced_moving_picture = "0"
log = "0.4" log = "0.4"
@@ -16,13 +16,12 @@ rust-i18n = "3"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
time-format = "1.2" time-format = "1.2"
toml = "1"
[dev-dependencies] [dev-dependencies]
rand = "0.10" rand = "0.10"
[profile.dev] [profile.dev]
opt-level = 2 opt-level = 3
codegen-units = 16 codegen-units = 16
[profile.release] [profile.release]
@@ -31,7 +30,8 @@ debug = false
incremental = false incremental = false
codegen-units = 1 codegen-units = 1
# We need level 3 for tiny-skia otherwise render is lagging # We need level 3 for tiny-skia otherwise render is lagging
opt-level = "s" # opt-level = "s"
opt-level = 3
strip = true strip = true
+81 -24
View File
@@ -20,7 +20,7 @@
use crate::kira_size::KiraSize; use crate::kira_size::KiraSize;
use log; use log;
use std::{collections::HashMap}; use std::collections::HashMap;
/// ///
/// size - device size in bytes /// size - device size in bytes
/// sector size - default 4096 /// sector size - default 4096
@@ -117,20 +117,25 @@ impl BlkDev {
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct BcachefsProp { pub struct BcachefsProp {
pub password: Option<String>, pub password: Option<String>,
pub comp_alg: Option<String>, pub comp_alg: Option<String>,
} }
impl BcachefsProp { impl BcachefsProp {
pub fn new(password: Option<String>, comp_alg: Option<String>) -> Self { pub fn new(password: Option<String>, comp_alg: Option<String>) -> Self {
Self { password:password, comp_alg: comp_alg } Self {
password: password,
comp_alg: comp_alg,
}
} }
pub fn default() -> Self { pub fn default() -> Self {
Self { password: None, comp_alg: None } Self {
password: None,
comp_alg: None,
}
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@@ -208,7 +213,7 @@ impl FSType {
pub enum PartRole { pub enum PartRole {
EFI, EFI,
ROOT, ROOT,
SWAP SWAP,
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@@ -230,6 +235,22 @@ impl std::fmt::Display for PartInfo {
} }
impl PartInfo { impl PartInfo {
///
/// calculate par end byte as 0 starting bytes index (for parted and such)
///
pub fn part_end(&self) -> KiraSize {
// important to shift here by 1 because disk index is starting from 0, and part end pointing to last byte of the partition.
(self.start + self.size) - KiraSize::new_b(1)
}
///
/// Returns zero based byte index of start of next (right after this one) partition
///
pub fn next_part_start(&self) -> KiraSize {
// important to shift here by 1 because disk index is starting from 0, and part end pointing to last byte of the partition.
self.start + self.size
}
pub fn from_hash_map(data: &HashMap<String, String>) -> Option<Self> { pub fn from_hash_map(data: &HashMap<String, String>) -> Option<Self> {
Some(Self { Some(Self {
name: data.get("NAME")?.clone(), name: data.get("NAME")?.clone(),
@@ -250,7 +271,9 @@ impl PartInfo {
} }
pub fn partlabel_dev(&self) -> Option<String> { pub fn partlabel_dev(&self) -> Option<String> {
self.gpt_label.as_ref().and_then(|l| Some(format!("/dev/disk/by-partlabel/{}", l))) self.gpt_label
.as_ref()
.and_then(|l| Some(format!("/dev/disk/by-partlabel/{}", l)))
} }
} }
@@ -260,9 +283,11 @@ fn get_dev_part_blocking(dev_name: &str) -> Result<Vec<PartInfo>, String> {
//"lsblk -o NAME,SIZE,FSTYPE -l -n /dev/nvme0n1" //"lsblk -o NAME,SIZE,FSTYPE -l -n /dev/nvme0n1"
// lsblk -o NAME,SIZE,FSTYPE,TYPE,PARTLABEL,LABEL,PARTFLAGS -b -P // lsblk -o NAME,SIZE,FSTYPE,TYPE,PARTLABEL,LABEL,PARTFLAGS -b -P
// -x NAME - sorting by name
match Command::new("lsblk") match Command::new("lsblk")
.args([ .args([
"-x",
"NAME",
"-o", "-o",
"NAME,SIZE,FSTYPE,TYPE,PARTLABEL,LABEL,MOUNTPOINT,PARTFLAGS", "NAME,SIZE,FSTYPE,TYPE,PARTLABEL,LABEL,MOUNTPOINT,PARTFLAGS",
"-b", "-b",
@@ -329,7 +354,7 @@ pub fn align_part(size: u64, start: u64, align: u64) -> Option<(u64, u64, u64)>
// decreasing end if not align // decreasing end if not align
let part_end = align_start + size; let part_end = align_start + size;
let end_mod = part_end % align; let end_mod = part_end % align;
log::debug!("part_end: {} end_mod: {}", part_end, end_mod);
let align_end = part_end - end_mod - 1; let align_end = part_end - end_mod - 1;
let align_size = align_end - align_start + 1; let align_size = align_end - align_start + 1;
@@ -342,7 +367,13 @@ pub fn align_part(size: u64, start: u64, align: u64) -> Option<(u64, u64, u64)>
); );
return None; return None;
} }
log::debug!(
"align_size: {}, align_start:{}, align_end: {} end_mod: {}",
align_size,
align_start,
align_end,
end_mod
);
Some((align_size, align_start, align_end)) Some((align_size, align_start, align_end))
} }
@@ -353,10 +384,17 @@ pub struct PartLayout {
pub part_list: Vec<PartInfo>, pub part_list: Vec<PartInfo>,
} }
///
/// GPT requires 33x512 sectors at the very end of the disk (16896 bytes):
/// 32 sectors - backup Partition Entry Array
/// 1 sector - backup GPT header
///
impl PartLayout { impl PartLayout {
pub fn new(dev: BlkDev) -> Self { pub fn new(dev: BlkDev) -> Self {
// 16896 - reserved space at the dev end for gpt
let usable_space = dev.size - KiraSize::new_b(16896);
Self { Self {
empty_space: dev.size, empty_space: usable_space,
dev: dev, dev: dev,
part_list: Vec::new(), part_list: Vec::new(),
} }
@@ -374,11 +412,11 @@ impl PartLayout {
}) })
} }
pub fn new_table(mut self) -> Self { // pub fn new_table(mut self) -> Self {
self.empty_space = self.dev.size; // self.empty_space = self.dev.size;
self.part_list = Vec::new(); // self.part_list = Vec::new();
self // self
} // }
pub fn add_part( pub fn add_part(
mut self, mut self,
@@ -390,19 +428,29 @@ impl PartLayout {
role: Option<PartRole>, role: Option<PartRole>,
) -> Self { ) -> Self {
let part_start = if self.part_list.is_empty() { let part_start = if self.part_list.is_empty() {
// need to substract 2 mb offset from disk start.
self.empty_space = self.empty_space - KiraSize::new_mb(2);
KiraSize::new_mb(2) KiraSize::new_mb(2)
} else { } else {
self.dev.size - self.empty_space // last part end + 1
self.part_list.last().unwrap().next_part_start()
}; };
let (size, start, _) = let (a_size, a_start, _) =
align_part(part_size.b(), part_start.b(), self.dev.sector_size.b()).unwrap(); align_part(part_size.b(), part_start.b(), self.dev.sector_size.b()).unwrap();
log::debug!(
"PartLayout.add_part gpt_label{:?}, size_asked:{}, size_al:{}",
gpt_label,
part_size,
a_size
);
let part_name = format!("{}p{}", self.dev.name, self.part_list.len() + 1); let part_name = format!("{}p{}", self.dev.name, self.part_list.len() + 1);
self.part_list.push(PartInfo { self.part_list.push(PartInfo {
name: part_name, name: part_name,
size: KiraSize::new_b(size), size: KiraSize::new_b(a_size),
start: KiraSize::new_b(start), start: KiraSize::new_b(a_start),
fs_type: fs_type, fs_type: fs_type,
gpt_label: gpt_label, gpt_label: gpt_label,
fs_label: fs_label, fs_label: fs_label,
@@ -410,10 +458,14 @@ impl PartLayout {
role: role, role: role,
}); });
self.empty_space = self.empty_space - KiraSize::new_b(size); self.empty_space = self.empty_space - KiraSize::new_b(a_size);
self self
} }
///
/// Use this to add partition of (disk_empty_space - reserve_space)
/// Specifically to leave some space at the end for SWAP and such
///
pub fn add_part_reserve( pub fn add_part_reserve(
self, self,
reserve_space: KiraSize, reserve_space: KiraSize,
@@ -427,7 +479,13 @@ impl PartLayout {
self.add_part(p_size, fs_type, gpt_label, fs_label, mount_point, role) self.add_part(p_size, fs_type, gpt_label, fs_label, mount_point, role)
} }
pub fn gen_kira_layout(dev: BlkDev, efi_size: KiraSize, swap_size: KiraSize, maybe_password: Option<String>, maybe_compr: Option<String>) -> Self { pub fn gen_kira_layout(
dev: BlkDev,
efi_size: KiraSize,
swap_size: KiraSize,
maybe_password: Option<String>,
maybe_compr: Option<String>,
) -> Self {
let mut res: PartLayout = PartLayout::new(dev); let mut res: PartLayout = PartLayout::new(dev);
// UEFI partition // UEFI partition
@@ -454,7 +512,7 @@ impl PartLayout {
res = res.add_part( res = res.add_part(
swap_size, swap_size,
FSType::SWAP, FSType::SWAP,
Some("swap".into()), Some("bee-swap".into()),
None, None,
Some("SWAP".into()), Some("SWAP".into()),
Some(PartRole::SWAP), Some(PartRole::SWAP),
@@ -465,7 +523,6 @@ impl PartLayout {
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use rand::RngExt; use rand::RngExt;
+43 -22
View File
@@ -19,18 +19,25 @@
*/ */
use crate::kira_disk_layout::*; use crate::kira_disk_layout::*;
use std::process::Command; use crate::kira_size::KiraSize;
use std::fs; use std::fs;
use std::process::Command;
#[derive(Debug)] #[derive(Debug)]
pub struct CommandFailed{ pub struct CommandFailed {
stderr: Vec<u8>, stderr: Vec<u8>,
cmd: String, cmd: String,
} }
impl std::fmt::Display for CommandFailed { impl std::fmt::Display for CommandFailed {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "Command failed! Command: {}; Stderr: {}", self.cmd, String::from_utf8(self.stderr.clone()).unwrap_or_else(|_|{"STDEER IS NOT VALID UTF-8".to_string()})) write!(
f,
"Command failed! Command: {}; Stderr: {}",
self.cmd,
String::from_utf8(self.stderr.clone())
.unwrap_or_else(|_| { "STDEER IS NOT VALID UTF-8".to_string() })
)
} }
} }
@@ -124,7 +131,10 @@ pub fn dinit_sync_time_chrony() -> Result<(), ExecCommandError> {
/// Install base system /// Install base system
/// basestrap /mnt base base-devel dinit elogind-dinit /// basestrap /mnt base base-devel dinit elogind-dinit
pub fn basestrap_dinit(root_dir: &str) -> Result<(), ExecCommandError> { pub fn basestrap_dinit(root_dir: &str) -> Result<(), ExecCommandError> {
exec_command("basestrap", &vec![root_dir, "base", "base-devel", "dinit", "elogind-dinit"]) exec_command(
"basestrap",
&vec![root_dir, "base", "base-devel", "dinit", "elogind-dinit"],
)
} }
/// Executes parted command with given arguments /// Executes parted command with given arguments
@@ -151,12 +161,7 @@ fn parted_get_last_part_num(dev: &BlkDev) -> Result<u32, ExecCommandError> {
/// Its blocking function /// Its blocking function
pub fn parted_init_gpt_part_table(dev: &BlkDev) -> Result<(), ExecCommandError> { pub fn parted_init_gpt_part_table(dev: &BlkDev) -> Result<(), ExecCommandError> {
let dev_full_name = dev.full_name(); let dev_full_name = dev.full_name();
let args = vec![ let args = vec!["--script", &dev_full_name, "mklabel", "gpt"];
"--script",
&dev_full_name,
"mklabel",
"gpt",
];
exec_command("parted", &args) exec_command("parted", &args)
} }
@@ -166,7 +171,8 @@ const LINUX_ROOT_X86_64_TYPE: &str = "4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709";
/// It assumes that we add partitions sequentially to empty space (for part attributes settings) /// It assumes that we add partitions sequentially to empty space (for part attributes settings)
/// Otherwise can produce bonkers layout /// Otherwise can produce bonkers layout
pub fn parted_mkpart(dev: &BlkDev, part: &PartInfo) -> Result<(), ExecCommandError> { pub fn parted_mkpart(dev: &BlkDev, part: &PartInfo) -> Result<(), ExecCommandError> {
let part_end = part.start + part.size; // important to shift here by 1 because disk index is starting from 0, and part end pointing to last byte of the partition.
let part_end = part.part_end();
// gpt label should be in double qutes // gpt label should be in double qutes
let gpt_label = if let Some(s) = &part.gpt_label { let gpt_label = if let Some(s) = &part.gpt_label {
@@ -174,6 +180,14 @@ pub fn parted_mkpart(dev: &BlkDev, part: &PartInfo) -> Result<(), ExecCommandErr
} else { } else {
"\"\"".to_string() "\"\"".to_string()
}; };
log::debug!(
"Creatin partition dev:{}, label:{}, fs_type:{}, start:{}, end:{}",
dev.full_name(),
gpt_label,
part.fs_type.to_parted_str(),
part.start.to_parted_bytes_str(),
part_end.to_parted_bytes_str()
);
// creating partition // creating partition
exec_parted(&vec![ exec_parted(&vec![
"--script", "--script",
@@ -218,7 +232,7 @@ pub fn parted_mkpart(dev: &BlkDev, part: &PartInfo) -> Result<(), ExecCommandErr
} }
/// creating single drive bcachefs volume /// creating single drive bcachefs volume
/// compression: lz4, zstd /// compression: lz4, zstd
pub fn bcachefs_format( pub fn bcachefs_format(
dev_name: &str, dev_name: &str,
compression: Option<String>, compression: Option<String>,
@@ -255,13 +269,11 @@ pub fn bcachefs_format(
/// unlok encrypted bcache volume /// unlok encrypted bcache volume
pub fn bcachefs_unlock(dev_name: &str, pass: &str) -> Result<(), ExecCommandError> { pub fn bcachefs_unlock(dev_name: &str, pass: &str) -> Result<(), ExecCommandError> {
// bcachefs unlock --file=/tmp/bzzpsspass.txt /dev/loop0 // bcachefs unlock --file=/tmp/bzzpsspass.txt /dev/loop0
let arg = vec!["unlock", "--file=/tmp/bzzpsspass.txt ", dev_name]; let arg = vec!["unlock", "--file=/tmp/bzzpsspass.txt ", dev_name];
// creating tmp file with password // creating tmp file with password
fs::write("/tmp/bzzpsspass.txt", &pass)?; fs::write("/tmp/bzzpsspass.txt", &pass)?;
let out = exec_command("bcachefs", &arg); let out = exec_command("bcachefs", &arg);
// ignore any errors while deleting pass tmp file // ignore any errors while deleting pass tmp file
let _ = fs::remove_file("/tmp/bzzpsspass.txt"); let _ = fs::remove_file("/tmp/bzzpsspass.txt");
@@ -281,6 +293,16 @@ pub fn bcachefs_mount(dev_name: &str, mount_point: &str) -> Result<(), ExecComma
exec_command("mount", &vec!["-t", "bcachefs", dev_name, mount_point]) exec_command("mount", &vec!["-t", "bcachefs", dev_name, mount_point])
} }
pub fn mount_fs(dev_name: &str, mount_point: &str) -> Result<(), ExecCommandError> {
// sudo mount -t bcachefs /dev/loop0 /mnt/test
exec_command("mount", &vec![dev_name, mount_point])
}
pub fn swapon(dev_name: &str) -> Result<(), ExecCommandError> {
exec_command("swapon", &vec![dev_name])
}
pub fn fatlabel(dev: &str, label: &str) -> Result<(), ExecCommandError> { pub fn fatlabel(dev: &str, label: &str) -> Result<(), ExecCommandError> {
//fatlabel /dev/sda1 ESP //fatlabel /dev/sda1 ESP
exec_command("fatlabel", &vec![dev, label]) exec_command("fatlabel", &vec![dev, label])
@@ -292,10 +314,10 @@ pub fn mkfs_fat32(dev: &str, maybe_label: Option<&str>) -> Result<(), ExecComman
// if need to set label // if need to set label
if let Some(label) = maybe_label { if let Some(label) = maybe_label {
fatlabel(dev, label) fatlabel(dev, label)
} else { } else {
Ok(()) Ok(())
} }
} }
/// mkfs.fat -F 32 /dev/sda1 /// mkfs.fat -F 32 /dev/sda1
@@ -304,8 +326,7 @@ pub fn mkfs_esp(dev: &str) -> Result<(), ExecCommandError> {
mkfs_fat32(dev, Some("ESP")) mkfs_fat32(dev, Some("ESP"))
} }
pub fn mkswap(dev: &str) -> Result<(), ExecCommandError> { pub fn mkswap(dev: &str) -> Result<(), ExecCommandError> {
//mkswap -L SWAP /dev/sda4 //mkswap -L SWAP /dev/sda4
exec_command("mkswap", &vec!["L", "SWAP", dev]) exec_command("mkswap", &vec!["-L", "bee-swap", dev])
} }
+1 -1
View File
@@ -245,9 +245,9 @@ fn update(k_state: &mut KiraState, message: Message) -> Task<Message> {
if let Views::Keyboard(keyboard_view) = &mut k_state.current_view { if let Views::Keyboard(keyboard_view) = &mut k_state.current_view {
match keyboard_view.update(keyboard_msg) { match keyboard_view.update(keyboard_msg) {
StageAction::Next(keyboard_res) => { StageAction::Next(keyboard_res) => {
k_state.k_config = keyboard_res;
match stages::partition::PartitionStage::new(k_state.k_config.clone()) { match stages::partition::PartitionStage::new(k_state.k_config.clone()) {
Ok(part_stage) => { Ok(part_stage) => {
k_state.k_config = keyboard_res;
let s_state = std::mem::replace( let s_state = std::mem::replace(
&mut k_state.current_view, &mut k_state.current_view,
Views::Partition(part_stage), Views::Partition(part_stage),
Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

+2 -113
View File
@@ -18,106 +18,9 @@
This file contains basic enums and structs to be used with stages. This file contains basic enums and structs to be used with stages.
*/ */
use iced::wgpu::naga::compact::KeepUnused::No;
use crate::stages; use crate::stages;
// #[derive(Debug, Clone)]
// pub enum StageResult {
// WelcomeStageResult(stages::welcome::WelcomeStageResult),
// NetworkStageResult(stages::network::NetworkStageResult),
// LocaleStageResult(stages::locale::LocaleStageResult),
// TimeZoneStageResult(stages::timezone::TimeZoneStageResult),
// KeyboardStageResult(stages::keyboard::KeyboardStageResult),
// SecurityStageResult(stages::security::SecurityStageResult),
// PartitionStageResult(stages::partition::PartitionStageResult),
// None,
// }
// impl StageResult {
// pub fn name(&self) -> String {
// match self {
// Self::LocaleStageResult(_) => "locale".into(),
// Self::WelcomeStageResult(_) => "welcome".into(),
// Self::NetworkStageResult(_) => "network".into(),
// Self::TimeZoneStageResult(_) => "timezone".into(),
// Self::KeyboardStageResult(_) => "keyboard".into(),
// Self::PartitionStageResult(_) => "partition".into(),
// Self::SecurityStageResult(_) => "security".into(),
// Self::None => "none".into(),
// }
// }
// }
// impl StageResult {
// pub fn new(name: &str) -> Self {
// Self {
// name: name.into(),
// config: None,
// error: None,
// }
// }
// pub fn add_error(mut self, ex: String) -> Self {
// self.error = Some(ex);
// self
// }
// pub fn add_val(mut self, val_name: &str, conf_val: ConfigValue) -> Self {
// match &mut self.config {
// Some(c) => {
// c.insert(val_name.into(), conf_val);
// }
// None => {
// self.config = Some(HashMap::from([(val_name.into(), conf_val)]));
// }
// }
// self
// }
// pub fn add_val_string(self, val_name: &str, v: String) -> Self {
// self.add_val(val_name, ConfigValue::String(v))
// }
// pub fn add_val_bool(self, val_name: &str, v: bool) -> Self {
// self.add_val(val_name, ConfigValue::Bool(v))
// }
// pub fn add_val_u64(self, val_name: &str, v: u64) -> Self {
// self.add_val(val_name, ConfigValue::U64(v))
// }
// pub fn get_val(&self, val_name: &str) -> Option<ConfigValue> {
// let v = self
// .config
// .as_ref()
// .and_then(|hm| hm.get(val_name).cloned());
// return v;
// }
// pub fn get_val_str(&self, val_name: &str) -> Option<String> {
// match self.get_val(val_name) {
// Some(ConfigValue::String(v)) => Some(v),
// _ => None,
// }
// }
// pub fn get_val_bool(&self, val_name: &str) -> Option<bool> {
// match self.get_val(val_name) {
// Some(ConfigValue::Bool(v)) => Some(v),
// _ => None,
// }
// }
// pub fn get_val_part_layout(&self, val_name: &str) -> Option<PartLayout> {
// match self.get_val(val_name) {
// Some(ConfigValue::PartLayout(v)) => Some(v),
// _ => None,
// }
// }
// }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct KiraConfig { pub struct KiraConfig {
pub res_welcome: Option<stages::welcome::WelcomeStageResult>, pub res_welcome: Option<stages::welcome::WelcomeStageResult>,
@@ -128,7 +31,7 @@ pub struct KiraConfig {
pub res_keyboard: Option<stages::keyboard::KeyboardStageResult>, pub res_keyboard: Option<stages::keyboard::KeyboardStageResult>,
pub res_partition: Option<stages::partition::PartitionStageResult>, pub res_partition: Option<stages::partition::PartitionStageResult>,
pub res_security: Option<stages::security::SecurityStageResult>, pub res_security: Option<stages::security::SecurityStageResult>,
pub res_install: bool, pub res_install: Option<stages::install::InstallStageResult>,
} }
impl Default for KiraConfig { impl Default for KiraConfig {
@@ -142,25 +45,11 @@ impl Default for KiraConfig {
res_keyboard: None, res_keyboard: None,
res_partition: None, res_partition: None,
res_security: None, res_security: None,
res_install: false, res_install: None,
} }
} }
} }
// impl KiraConfig {
// pub fn get_stage(&self, name: &str) -> Option<StageResult> {
// self.config_trail
// .iter()
// .find(|v| v.name() == name)
// .and_then(|v| Some(v.clone()))
// }
// pub fn pop_last(&mut self) -> Option<StageResult> {
// self.config_trail.pop()
// }
// pub fn push(&mut self, stage_result: StageResult) {
// self.config_trail.push(stage_result);
// }
// }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum StageAction { pub enum StageAction {
+58 -93
View File
@@ -18,6 +18,8 @@
Actual installation script. Actual installation script.
*/ */
use std::path::Path;
use crate::{ use crate::{
kira_disk_layout::{self, BlkDev, FSType, PartLayout, PartRole}, kira_disk_layout::{self, BlkDev, FSType, PartLayout, PartRole},
kira_size::KiraSize, kira_size::KiraSize,
@@ -37,6 +39,8 @@ use log;
use rust_i18n::t; use rust_i18n::t;
const EFI_BOOT_MOUNT_POINT: &str = "/beefi"; const EFI_BOOT_MOUNT_POINT: &str = "/beefi";
const MNT_DIR: &str = "/mnt/inst_root";
const ROOT_PARTLABEL_DEV: &str = "/dev/disk/by-partlabel/bee-root";
/// Creates new GPT table and partitions from PartLayout /// Creates new GPT table and partitions from PartLayout
pub fn create_partitions(part_layout: &PartLayout) -> Result<(), ExecCommandError> { pub fn create_partitions(part_layout: &PartLayout) -> Result<(), ExecCommandError> {
@@ -59,11 +63,7 @@ pub fn bcachefs_init(
dev_name: &str, dev_name: &str,
mnt_dir: &str, mnt_dir: &str,
password: Option<String>, password: Option<String>,
comp_alg: Option<String>,
) -> Result<(), ExecCommandError> { ) -> Result<(), ExecCommandError> {
// format device
kira_system::bcachefs_format(dev_name, comp_alg, password.clone())?;
// if encryption used - unlock drive // if encryption used - unlock drive
if let Some(pass) = password { if let Some(pass) = password {
kira_system::bcachefs_unlock(dev_name, pass.as_str())?; kira_system::bcachefs_unlock(dev_name, pass.as_str())?;
@@ -88,6 +88,15 @@ pub fn bcachefs_init(
} }
pub fn init_disk(part_layout: &PartLayout, mnt_dir: &str) -> Result<(), ExecCommandError> { pub fn init_disk(part_layout: &PartLayout, mnt_dir: &str) -> Result<(), ExecCommandError> {
let mnt_path = Path::new(mnt_dir);
log::info!("Cheking is MNT path exists: {}", mnt_dir);
if !mnt_path.exists() {
log::info!("MNT path do not exist, creating it...");
std::fs::create_dir_all(mnt_path)?;
}
// use parted to create partition gpt layout // use parted to create partition gpt layout
create_partitions(part_layout)?; create_partitions(part_layout)?;
@@ -102,12 +111,11 @@ pub fn init_disk(part_layout: &PartLayout, mnt_dir: &str) -> Result<(), ExecComm
Some(PartRole::ROOT) => { Some(PartRole::ROOT) => {
if let Some(part_l) = part.partlabel_dev() { if let Some(part_l) = part.partlabel_dev() {
if let FSType::BCACHEFS(bc_par) = &part.fs_type { if let FSType::BCACHEFS(bc_par) = &part.fs_type {
bcachefs_init( log::info!("Formating root pertition.");
&part_l, kira_system::bcachefs_format(&part_l, bc_par.password.clone(), bc_par.password.clone())?;
mnt_dir, // init root
bc_par.password.clone(), log::info!("Mount and init root partition.");
bc_par.comp_alg.clone(), bcachefs_init(ROOT_PARTLABEL_DEV, mnt_dir, bc_par.password.clone())?;
)?;
} else { } else {
return Err(ExecCommandError::Other( return Err(ExecCommandError::Other(
"ROOT partition is not BCACHEFS type!".into(), "ROOT partition is not BCACHEFS type!".into(),
@@ -135,12 +143,16 @@ enum InstallationState {
Error, Error,
} }
#[derive(Debug, Clone)]
pub struct InstallStageResult {
pub sucess: Result<(), String>,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct InstallStage { pub struct InstallStage {
state: InstallationState, state: InstallationState,
progress: f32, progress: f32,
progress_message: String, progress_message: String,
part_config: PartitionStageResult,
modal_backgroud: Color, modal_backgroud: Color,
k_config: KiraConfig, k_config: KiraConfig,
} }
@@ -167,95 +179,27 @@ async fn init_disk_async(part_layout: PartLayout, mnt_dir: String) -> Result<(),
blocking::unblock(move || init_disk(&part_layout, &mnt_dir)).await blocking::unblock(move || init_disk(&part_layout, &mnt_dir)).await
} }
fn partition_disk( fn do_install(
disk_layout: PartLayout, k_config: KiraConfig,
password: Option<String>,
compression: Option<String>,
mnt_dir: String,
) -> impl futures::Stream<Item = Result<(f32, String), ExecCommandError>> { ) -> impl futures::Stream<Item = Result<(f32, String), ExecCommandError>> {
use blocking;
iced::stream::channel( iced::stream::channel(
100, 100,
|mut output: Sender<Result<(f32, String), ExecCommandError>>| async move { |mut output: Sender<Result<(f32, String), ExecCommandError>>| async move {
//sleep(Duration::from_millis(10)).await; //sleep(Duration::from_millis(10)).await;
let disk_layout_cloned = disk_layout.clone(); let disk_layout = k_config.res_partition.unwrap().part_layout.clone();
// creating gpt partition table // creating gpt partition table
let res = init_disk_async(disk_layout_cloned, mnt_dir).await; let res = init_disk_async(disk_layout, MNT_DIR.into()).await;
let res_err = res.is_err();
output output
.send(res.map(|_| (1.1f32, "Formatting bcachefs".into()))) .send(res.map(|_| (1.1f32, "Formatting bcachefs".into())))
.await .await
.unwrap(); .unwrap();
if res.is_err() {
if res_err {
return; return;
} }
let res = init_disk_async(disk_layout_cloned).await;
output
.send(res.map(|_| (1.1f32, "Formatting bcachefs".into())))
.await
.unwrap();
if res.is_err() {
return;
}
// creating partitions
let dev = disk_layout.dev.clone();
let part_list = disk_layout.part_list.clone();
match output
.send(
blocking::unblock(move || {
let mut res = Ok(());
for part in part_list {
match kira_system::parted_mkpart(&dev, &part) {
Ok(_) => (),
Err(ex) => {
res = Err(ex);
break;
}
}
}
res
})
.await
.and(Ok((5.0f32, "Creating partitions".into()))),
)
.await
{
Err(ex) => {
log::error!("Error creating GPT partition table: {}", ex.to_string());
return;
}
_ => (),
};
// creating bcachefs filesystem
// /dev/disk/by-partlabel/
let compression_cloned = compression.clone();
let password_cloned = password.clone();
match output
.send(
blocking::unblock(move || {
bcachefs_init(
"/dev/disk/by-partlabel/bee-root",
compression_cloned,
password_cloned,
"/mnt/bzzpss-install",
)
})
.await
.and(Ok((10.0f32, "Creating partition table".into()))),
)
.await
{
Err(ex) => {
log::error!("Error creating GPT partition table: {}", ex.to_string());
return;
}
_ => (),
};
// Check if send fails (receiver dropped/cancelled) // Check if send fails (receiver dropped/cancelled)
// if output.send(res).await.is_err() { // if output.send(res).await.is_err() {
// return; // Exit early if UI is gone // return; // Exit early if UI is gone
@@ -267,6 +211,20 @@ fn partition_disk(
) )
} }
fn check_kconfig(k_config: &KiraConfig) -> Result<(), String> {
if k_config.res_welcome.is_none(){ Err("Missing wellcome stage result!".into())}
else if k_config.res_license == false { Err("License is NOT accepted!".into())}
else if k_config.res_locale.is_none(){ Err("Missing locale stage result!".into())}
else if k_config.res_network.is_none(){ Err("Missing network stage result!".into())}
else if k_config.res_keyboard.is_none(){ Err("Missing keyboard stage result!".into())}
else if k_config.res_timezone.is_none(){ Err("Missing timezone stage result!".into())}
else if k_config.res_partition.is_none(){ Err("Missing partition stage result!".into())}
else if k_config.res_security.is_none(){ Err("Missing security stage result!".into())}
else {
Ok(())
}
}
impl InstallStage { impl InstallStage {
pub fn new(k_config: KiraConfig) -> Self { pub fn new(k_config: KiraConfig) -> Self {
let mut modal_backgroud = kira_theming::main_theme().palette().background; let mut modal_backgroud = kira_theming::main_theme().palette().background;
@@ -276,13 +234,12 @@ impl InstallStage {
state: InstallationState::UserConfirmDialog, state: InstallationState::UserConfirmDialog,
progress: 0.0, progress: 0.0,
progress_message: String::new(), progress_message: String::new(),
part_config: k_config.res_partition.clone().expect("Partition stage result should be present in KiraConfig!"),
k_config: k_config, k_config: k_config,
} }
} }
fn gen_result(&mut self) -> KiraConfig { fn gen_result(&mut self) -> KiraConfig {
self.k_config.res_install = true; self.k_config.res_install = Some(InstallStageResult { sucess: Ok(()) });
self.k_config.clone() self.k_config.clone()
} }
@@ -290,16 +247,24 @@ impl InstallStage {
match message { match message {
Message::UserDenies => Update::StgAct(StageAction::Back), Message::UserDenies => Update::StgAct(StageAction::Back),
Message::UserConfirms => { Message::UserConfirms => {
log::info!("Cheking config...");
match check_kconfig(&self.k_config) {
Ok(()) => log::info!("Config looks good."),
Err(ex) => {
log::error!("{}", ex);
self.state = InstallationState::Error;
return Update::StgAct(StageAction::None);
}
}
// starting installation process here // starting installation process here
log::info!("Starting disk partitioning."); log::info!("Starting disk partitioning.");
self.state = InstallationState::Installing; self.state = InstallationState::Installing;
let disk_layout = self.part_config.part_layout.clone();
let disk_password = self.part_config.password.clone();
let disk_compression = Some("lz4".to_string());
Update::Task(Task::run( Update::Task(Task::run(
partition_disk(disk_layout, disk_password, disk_compression) do_install(self.k_config.clone()).map_err(|ex| ex.to_string()),
.map_err(|ex| ex.to_string()),
Message::UpdateProgress, Message::UpdateProgress,
)) ))
//Update::Task(Task::perform(, Message::PartitioningFinish)) //Update::Task(Task::perform(, Message::PartitioningFinish))
+1 -1
View File
@@ -18,7 +18,7 @@
This is Security stage, setup users logins and such This is Security stage, setup users logins and such
*/ */
use crate::stage::{StageAction, KiraConfig}; use crate::stage::{KiraConfig, StageAction};
use iced::{Alignment, Color, widget}; use iced::{Alignment, Color, widget};
use rust_i18n::t; use rust_i18n::t;