forked from lix-project/lix-installer
wip mac work
This commit is contained in:
parent
64e7423a0a
commit
a29baa2b33
234
src/actions/meta/darwin/create_apfs_volume.rs
Normal file
234
src/actions/meta/darwin/create_apfs_volume.rs
Normal file
|
@ -0,0 +1,234 @@
|
|||
use serde::Serialize;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::actions::base::{
|
||||
darwin::{
|
||||
BootstrapVolume, BootstrapVolumeError, CreateSyntheticObjects, CreateSyntheticObjectsError,
|
||||
CreateVolume, CreateVolumeError, EnableOwnership, EnableOwnershipError, EncryptVolume,
|
||||
EncryptVolumeError, UnmountVolume, UnmountVolumeError,
|
||||
},
|
||||
CreateDirectory, CreateDirectoryError, CreateFile, CreateFileError, CreateOrAppendFile,
|
||||
CreateOrAppendFileError,
|
||||
};
|
||||
use crate::actions::{Action, ActionDescription, ActionState, Actionable};
|
||||
|
||||
const NIX_VOLUME_MOUNTD_DEST: &str = "/Library/LaunchDaemons/org.nixos.darwin-store.plist";
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateApfsVolume {
|
||||
disk: PathBuf,
|
||||
name: String,
|
||||
case_sensitive: bool,
|
||||
encrypt: Option<String>,
|
||||
create_or_append_synthetic_conf: CreateOrAppendFile,
|
||||
create_synthetic_objects: CreateSyntheticObjects,
|
||||
unmount_volume: UnmountVolume,
|
||||
create_volume: CreateVolume,
|
||||
create_or_append_fstab: CreateOrAppendFile,
|
||||
encrypt_volume: Option<EncryptVolume>,
|
||||
bootstrap_volume: BootstrapVolume,
|
||||
enable_ownership: EnableOwnership,
|
||||
action_state: ActionState,
|
||||
}
|
||||
|
||||
impl CreateApfsVolume {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan(
|
||||
disk: impl AsRef<Path>,
|
||||
name: String,
|
||||
case_sensitive: bool,
|
||||
encrypt: Option<String>,
|
||||
) -> Result<Self, CreateApfsVolumeError> {
|
||||
let disk = disk.as_ref();
|
||||
let create_or_append_synthetic_conf = CreateOrAppendFile::plan(
|
||||
"/etc/synthetic.conf",
|
||||
"root".into(),
|
||||
"wheel".into(),
|
||||
0o0655,
|
||||
"nix".into(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let create_synthetic_objects = CreateSyntheticObjects::plan().await?;
|
||||
|
||||
let unmount_volume =
|
||||
UnmountVolume::plan(disk, name.clone(), case_sensitive, encrypt).await?;
|
||||
|
||||
let create_volume = CreateVolume::plan(disk, name.clone(), case_sensitive, encrypt).await?;
|
||||
|
||||
let create_or_append_fstab = CreateOrAppendFile::plan(
|
||||
"/etc/fstab",
|
||||
"root".into(),
|
||||
"root".into(),
|
||||
0o0655,
|
||||
"NAME={name} /nix apfs rw,noauto,nobrowse,suid,owners".into(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let encrypt_volume = if let Some(password) = encrypt {
|
||||
Some(EncryptVolume::plan(disk, password).await)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let bootstrap_volume = BootstrapVolume::plan(NIX_VOLUME_MOUNTD_DEST).await?;
|
||||
let enable_ownership = EnableOwnership::plan("/nix").await?;
|
||||
|
||||
Ok(Self {
|
||||
disk: disk.to_path_buf(),
|
||||
name,
|
||||
case_sensitive,
|
||||
encrypt,
|
||||
create_or_append_synthetic_conf,
|
||||
create_synthetic_objects,
|
||||
unmount_volume,
|
||||
create_volume,
|
||||
create_or_append_fstab,
|
||||
encrypt_volume,
|
||||
bootstrap_volume,
|
||||
enable_ownership,
|
||||
action_state: ActionState::Uncompleted,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Actionable for CreateApfsVolume {
|
||||
type Error = CreateApfsVolumeError;
|
||||
|
||||
fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||
let Self {
|
||||
disk,
|
||||
name,
|
||||
case_sensitive,
|
||||
encrypt,
|
||||
create_or_append_synthetic_conf,
|
||||
create_synthetic_objects,
|
||||
unmount_volume,
|
||||
create_volume,
|
||||
create_or_append_fstab,
|
||||
encrypt_volume,
|
||||
bootstrap_volume,
|
||||
enable_ownership,
|
||||
action_state: _,
|
||||
} = &self;
|
||||
if self.action_state == ActionState::Completed {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
format!("Create an APFS volume", destination.display()),
|
||||
vec![format!(
|
||||
"Create a writable, persistent systemd system extension.",
|
||||
)],
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all, fields(destination,))]
|
||||
async fn execute(&mut self) -> Result<(), Self::Error> {
|
||||
let Self {
|
||||
disk,
|
||||
name,
|
||||
case_sensitive,
|
||||
encrypt,
|
||||
create_or_append_synthetic_conf,
|
||||
create_synthetic_objects,
|
||||
unmount_volume,
|
||||
create_volume,
|
||||
create_or_append_fstab,
|
||||
encrypt_volume,
|
||||
bootstrap_volume,
|
||||
enable_ownership,
|
||||
action_state,
|
||||
} = self;
|
||||
if *action_state == ActionState::Completed {
|
||||
tracing::trace!("Already completed: Creating sysext");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Creating sysext");
|
||||
|
||||
for create_directory in create_directories {
|
||||
create_directory.execute().await?;
|
||||
}
|
||||
create_extension_release.execute().await?;
|
||||
create_bind_mount_unit.execute().await?;
|
||||
|
||||
tracing::trace!("Created sysext");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||
let Self {
|
||||
disk,
|
||||
name,
|
||||
case_sensitive,
|
||||
encrypt,
|
||||
create_or_append_synthetic_conf,
|
||||
create_synthetic_objects,
|
||||
unmount_volume,
|
||||
create_volume,
|
||||
create_or_append_fstab,
|
||||
encrypt_volume,
|
||||
bootstrap_volume,
|
||||
enable_ownership,
|
||||
action_state: _,
|
||||
} = &self;
|
||||
if self.action_state == ActionState::Uncompleted {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
format!("Remove the sysext located at `{}`", destination.display()),
|
||||
vec![],
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all, fields(destination,))]
|
||||
async fn revert(&mut self) -> Result<(), Self::Error> {
|
||||
let Self {
|
||||
disk,
|
||||
name,
|
||||
case_sensitive,
|
||||
encrypt,
|
||||
create_or_append_synthetic_conf,
|
||||
create_synthetic_objects,
|
||||
unmount_volume,
|
||||
create_volume,
|
||||
create_or_append_fstab,
|
||||
encrypt_volume,
|
||||
bootstrap_volume,
|
||||
enable_ownership,
|
||||
action_state,
|
||||
} = self;
|
||||
if *action_state == ActionState::Uncompleted {
|
||||
tracing::trace!("Already reverted: Removing sysext");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Removing sysext");
|
||||
|
||||
create_bind_mount_unit.revert().await?;
|
||||
|
||||
create_extension_release.revert().await?;
|
||||
|
||||
for create_directory in create_directories.iter_mut().rev() {
|
||||
create_directory.revert().await?;
|
||||
}
|
||||
|
||||
tracing::trace!("Removed sysext");
|
||||
*action_state = ActionState::Uncompleted;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CreateApfsVolume> for Action {
|
||||
fn from(v: CreateApfsVolume) -> Self {
|
||||
Action::CreateApfsVolume(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
pub enum CreateApfsVolumeError {
|
||||
#[error(transparent)]
|
||||
CreateOrAppendFile(#[from] CreateOrAppendFileError),
|
||||
}
|
2
src/actions/meta/darwin/mod.rs
Normal file
2
src/actions/meta/darwin/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
mod create_apfs_volume;
|
||||
pub use create_apfs_volume::{CreateApfsVolume, CreateApfsVolumeError};
|
|
@ -5,6 +5,7 @@ mod configure_shell_profile;
|
|||
mod create_nix_tree;
|
||||
mod create_systemd_sysext;
|
||||
mod create_users_and_group;
|
||||
pub mod darwin;
|
||||
mod place_channel_configuration;
|
||||
mod place_nix_configuration;
|
||||
mod provision_nix;
|
||||
|
|
|
@ -10,6 +10,7 @@ use base::{
|
|||
SystemdSysextMergeError,
|
||||
};
|
||||
use meta::{
|
||||
darwin::{CreateApfsVolume, CreateApfsVolumeError},
|
||||
ConfigureNix, ConfigureNixError, ConfigureShellProfile, ConfigureShellProfileError,
|
||||
CreateNixTree, CreateNixTreeError, CreateSystemdSysext, CreateSystemdSysextError,
|
||||
CreateUsersAndGroup, CreateUsersAndGroupError, PlaceChannelConfiguration,
|
||||
|
@ -56,26 +57,27 @@ impl ActionDescription {
|
|||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub enum Action {
|
||||
ConfigureNixDaemonService(ConfigureNixDaemonService),
|
||||
ConfigureNix(ConfigureNix),
|
||||
ConfigureNixDaemonService(ConfigureNixDaemonService),
|
||||
ConfigureShellProfile(ConfigureShellProfile),
|
||||
CreateApfsVolume(CreateApfsVolume),
|
||||
CreateDirectory(CreateDirectory),
|
||||
CreateSystemdSysext(CreateSystemdSysext),
|
||||
CreateFile(CreateFile),
|
||||
CreateGroup(CreateGroup),
|
||||
CreateOrAppendFile(CreateOrAppendFile),
|
||||
CreateNixTree(CreateNixTree),
|
||||
CreateOrAppendFile(CreateOrAppendFile),
|
||||
CreateSystemdSysext(CreateSystemdSysext),
|
||||
CreateUser(CreateUser),
|
||||
CreateUsersAndGroup(CreateUsersAndGroup),
|
||||
FetchNix(FetchNix),
|
||||
MoveUnpackedNix(MoveUnpackedNix),
|
||||
PlaceChannelConfiguration(PlaceChannelConfiguration),
|
||||
PlaceNixConfiguration(PlaceNixConfiguration),
|
||||
ProvisionNix(ProvisionNix),
|
||||
SetupDefaultProfile(SetupDefaultProfile),
|
||||
StartNixDaemon(StartNixDaemon),
|
||||
StartSystemdUnit(StartSystemdUnit),
|
||||
SystemdSysextMerge(SystemdSysextMerge),
|
||||
ProvisionNix(ProvisionNix),
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, serde::Serialize)]
|
||||
|
@ -87,6 +89,8 @@ pub enum ActionError {
|
|||
#[error("Attempted to revert an already reverted action")]
|
||||
AlreadyReverted(Action),
|
||||
#[error(transparent)]
|
||||
CreateApfsVolume(#[from] CreateApfsVolumeError),
|
||||
#[error(transparent)]
|
||||
ConfigureNixDaemonService(#[from] ConfigureNixDaemonServiceError),
|
||||
#[error(transparent)]
|
||||
ConfigureNix(#[from] ConfigureNixError),
|
||||
|
@ -133,102 +137,106 @@ impl Actionable for Action {
|
|||
type Error = ActionError;
|
||||
fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||
match self {
|
||||
Action::ConfigureNixDaemonService(i) => i.describe_execute(),
|
||||
Action::ConfigureNix(i) => i.describe_execute(),
|
||||
Action::ConfigureNixDaemonService(i) => i.describe_execute(),
|
||||
Action::ConfigureShellProfile(i) => i.describe_execute(),
|
||||
Action::CreateApfsVolume(i) => i.describe_execute(),
|
||||
Action::CreateDirectory(i) => i.describe_execute(),
|
||||
Action::CreateSystemdSysext(i) => i.describe_execute(),
|
||||
Action::CreateFile(i) => i.describe_execute(),
|
||||
Action::CreateGroup(i) => i.describe_execute(),
|
||||
Action::CreateOrAppendFile(i) => i.describe_execute(),
|
||||
Action::CreateNixTree(i) => i.describe_execute(),
|
||||
Action::CreateOrAppendFile(i) => i.describe_execute(),
|
||||
Action::CreateSystemdSysext(i) => i.describe_execute(),
|
||||
Action::CreateUser(i) => i.describe_execute(),
|
||||
Action::CreateUsersAndGroup(i) => i.describe_execute(),
|
||||
Action::FetchNix(i) => i.describe_execute(),
|
||||
Action::MoveUnpackedNix(i) => i.describe_execute(),
|
||||
Action::PlaceChannelConfiguration(i) => i.describe_execute(),
|
||||
Action::PlaceNixConfiguration(i) => i.describe_execute(),
|
||||
Action::ProvisionNix(i) => i.describe_execute(),
|
||||
Action::SetupDefaultProfile(i) => i.describe_execute(),
|
||||
Action::StartNixDaemon(i) => i.describe_execute(),
|
||||
Action::StartSystemdUnit(i) => i.describe_execute(),
|
||||
Action::SystemdSysextMerge(i) => i.describe_execute(),
|
||||
Action::ProvisionNix(i) => i.describe_execute(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn execute(&mut self) -> Result<(), Self::Error> {
|
||||
match self {
|
||||
Action::ConfigureNixDaemonService(i) => i.execute().await?,
|
||||
Action::ConfigureNix(i) => i.execute().await?,
|
||||
Action::ConfigureNixDaemonService(i) => i.execute().await?,
|
||||
Action::ConfigureShellProfile(i) => i.execute().await?,
|
||||
Action::CreateApfsVolume(i) => i.execute().await?,
|
||||
Action::CreateDirectory(i) => i.execute().await?,
|
||||
Action::CreateSystemdSysext(i) => i.execute().await?,
|
||||
Action::CreateFile(i) => i.execute().await?,
|
||||
Action::CreateGroup(i) => i.execute().await?,
|
||||
Action::CreateOrAppendFile(i) => i.execute().await?,
|
||||
Action::CreateNixTree(i) => i.execute().await?,
|
||||
Action::CreateOrAppendFile(i) => i.execute().await?,
|
||||
Action::CreateSystemdSysext(i) => i.execute().await?,
|
||||
Action::CreateUser(i) => i.execute().await?,
|
||||
Action::CreateUsersAndGroup(i) => i.execute().await?,
|
||||
Action::FetchNix(i) => i.execute().await?,
|
||||
Action::MoveUnpackedNix(i) => i.execute().await?,
|
||||
Action::PlaceChannelConfiguration(i) => i.execute().await?,
|
||||
Action::PlaceNixConfiguration(i) => i.execute().await?,
|
||||
Action::ProvisionNix(i) => i.execute().await?,
|
||||
Action::SetupDefaultProfile(i) => i.execute().await?,
|
||||
Action::StartNixDaemon(i) => i.execute().await?,
|
||||
Action::StartSystemdUnit(i) => i.execute().await?,
|
||||
Action::SystemdSysextMerge(i) => i.execute().await?,
|
||||
Action::ProvisionNix(i) => i.execute().await?,
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||
match self {
|
||||
Action::ConfigureNixDaemonService(i) => i.describe_revert(),
|
||||
Action::ConfigureNix(i) => i.describe_revert(),
|
||||
Action::ConfigureNixDaemonService(i) => i.describe_revert(),
|
||||
Action::ConfigureShellProfile(i) => i.describe_revert(),
|
||||
Action::CreateApfsVolume(i) => i.describe_revert(),
|
||||
Action::CreateDirectory(i) => i.describe_revert(),
|
||||
Action::CreateSystemdSysext(i) => i.describe_revert(),
|
||||
Action::CreateFile(i) => i.describe_revert(),
|
||||
Action::CreateGroup(i) => i.describe_revert(),
|
||||
Action::CreateOrAppendFile(i) => i.describe_revert(),
|
||||
Action::CreateNixTree(i) => i.describe_revert(),
|
||||
Action::CreateOrAppendFile(i) => i.describe_revert(),
|
||||
Action::CreateSystemdSysext(i) => i.describe_revert(),
|
||||
Action::CreateUser(i) => i.describe_revert(),
|
||||
Action::CreateUsersAndGroup(i) => i.describe_revert(),
|
||||
Action::FetchNix(i) => i.describe_revert(),
|
||||
Action::MoveUnpackedNix(i) => i.describe_revert(),
|
||||
Action::PlaceChannelConfiguration(i) => i.describe_revert(),
|
||||
Action::PlaceNixConfiguration(i) => i.describe_revert(),
|
||||
Action::ProvisionNix(i) => i.describe_revert(),
|
||||
Action::SetupDefaultProfile(i) => i.describe_revert(),
|
||||
Action::StartNixDaemon(i) => i.describe_revert(),
|
||||
Action::StartSystemdUnit(i) => i.describe_revert(),
|
||||
Action::SystemdSysextMerge(i) => i.describe_revert(),
|
||||
Action::ProvisionNix(i) => i.describe_revert(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn revert(&mut self) -> Result<(), Self::Error> {
|
||||
match self {
|
||||
Action::ConfigureNixDaemonService(i) => i.revert().await?,
|
||||
Action::ConfigureNix(i) => i.revert().await?,
|
||||
Action::ConfigureNixDaemonService(i) => i.revert().await?,
|
||||
Action::ConfigureShellProfile(i) => i.revert().await?,
|
||||
Action::CreateApfsVolume(i) => i.revert().await?,
|
||||
Action::CreateDirectory(i) => i.revert().await?,
|
||||
Action::CreateSystemdSysext(i) => i.revert().await?,
|
||||
Action::CreateFile(i) => i.revert().await?,
|
||||
Action::CreateGroup(i) => i.revert().await?,
|
||||
Action::CreateOrAppendFile(i) => i.revert().await?,
|
||||
Action::CreateNixTree(i) => i.revert().await?,
|
||||
Action::CreateOrAppendFile(i) => i.revert().await?,
|
||||
Action::CreateSystemdSysext(i) => i.revert().await?,
|
||||
Action::CreateUser(i) => i.revert().await?,
|
||||
Action::CreateUsersAndGroup(i) => i.revert().await?,
|
||||
Action::FetchNix(i) => i.revert().await?,
|
||||
Action::MoveUnpackedNix(i) => i.revert().await?,
|
||||
Action::PlaceChannelConfiguration(i) => i.revert().await?,
|
||||
Action::PlaceNixConfiguration(i) => i.revert().await?,
|
||||
Action::ProvisionNix(i) => i.revert().await?,
|
||||
Action::SetupDefaultProfile(i) => i.revert().await?,
|
||||
Action::StartNixDaemon(i) => i.revert().await?,
|
||||
Action::StartSystemdUnit(i) => i.revert().await?,
|
||||
Action::SystemdSysextMerge(i) => i.revert().await?,
|
||||
Action::ProvisionNix(i) => i.revert().await?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
use crate::{planner::Plannable, Planner};
|
||||
use crate::{
|
||||
actions::{
|
||||
meta::{darwin::CreateApfsVolume, ConfigureNix, ProvisionNix, StartNixDaemon},
|
||||
Action, ActionError,
|
||||
},
|
||||
planner::Plannable,
|
||||
InstallPlan, Planner,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)]
|
||||
pub struct DarwinMultiUser;
|
||||
|
@ -11,7 +18,32 @@ impl Plannable for DarwinMultiUser {
|
|||
async fn plan(
|
||||
settings: crate::InstallSettings,
|
||||
) -> Result<crate::InstallPlan, crate::planner::PlannerError> {
|
||||
todo!()
|
||||
Ok(InstallPlan {
|
||||
planner: Self.into(),
|
||||
settings: settings.clone(),
|
||||
actions: vec![
|
||||
// Create Volume step:
|
||||
//
|
||||
// setup_Synthetic -> create_synthetic_objects
|
||||
// Unmount -> create_volume -> Setup_fstab -> maybe encrypt_volume -> launchctl bootstrap -> launchctl kickstart -> await_volume -> maybe enableOwnership
|
||||
CreateApfsVolume::plan(settings.clone())
|
||||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
ProvisionNix::plan(settings.clone())
|
||||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
ConfigureNix::plan(settings)
|
||||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
StartNixDaemon::plan()
|
||||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue