mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-04 06:19:44 +00:00
feat: preserve volumes on failed install + migrate ext4 to btrfs
- COW snapshot (cp --reflink=always) of package volumes before install/update; restore on failure, remove on success - Automatic ext4→btrfs conversion via btrfs-convert during disk attach with e2fsck pre-check and post-conversion defrag - Probe package-data filesystem during setup.disk.list (on both disk and partition level) so the UI can warn about ext4 conversion - Setup wizard preserve-overwrite dialog shows ext4 warning with backup acknowledgment checkbox before allowing preserve
This commit is contained in:
@@ -422,11 +422,15 @@ impl Service {
|
||||
tracing::error!("Error installing service: {e}");
|
||||
tracing::debug!("{e:?}")
|
||||
}) {
|
||||
crate::volume::remove_install_backup(id).await.log_err();
|
||||
return Ok(Some(service));
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanup(ctx, id, false).await.log_err();
|
||||
crate::volume::restore_volumes_from_install_backup(id)
|
||||
.await
|
||||
.log_err();
|
||||
ctx.db
|
||||
.mutate(|v| v.as_public_mut().as_package_data_mut().remove(id))
|
||||
.await
|
||||
@@ -461,37 +465,60 @@ impl Service {
|
||||
tracing::error!("Error installing service: {e}");
|
||||
tracing::debug!("{e:?}")
|
||||
}) {
|
||||
crate::volume::remove_install_backup(id).await.log_err();
|
||||
return Ok(Some(service));
|
||||
}
|
||||
}
|
||||
}
|
||||
let s9pk = S9pk::open(s9pk_path, Some(id)).await?;
|
||||
ctx.db
|
||||
.mutate({
|
||||
|db| {
|
||||
db.as_public_mut()
|
||||
.as_package_data_mut()
|
||||
.as_idx_mut(id)
|
||||
.or_not_found(id)?
|
||||
.as_state_info_mut()
|
||||
.map_mutate(|s| {
|
||||
if let PackageState::Updating(UpdatingState {
|
||||
manifest, ..
|
||||
}) = s
|
||||
{
|
||||
Ok(PackageState::Installed(InstalledState { manifest }))
|
||||
} else {
|
||||
Err(Error::new(
|
||||
eyre!("{}", t!("service.mod.race-condition-detected")),
|
||||
ErrorKind::Database,
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
.await
|
||||
.result?;
|
||||
handle_installed(s9pk).await
|
||||
match async {
|
||||
let s9pk = S9pk::open(s9pk_path, Some(id)).await?;
|
||||
ctx.db
|
||||
.mutate({
|
||||
|db| {
|
||||
db.as_public_mut()
|
||||
.as_package_data_mut()
|
||||
.as_idx_mut(id)
|
||||
.or_not_found(id)?
|
||||
.as_state_info_mut()
|
||||
.map_mutate(|s| {
|
||||
if let PackageState::Updating(UpdatingState {
|
||||
manifest,
|
||||
..
|
||||
}) = s
|
||||
{
|
||||
Ok(PackageState::Installed(InstalledState { manifest }))
|
||||
} else {
|
||||
Err(Error::new(
|
||||
eyre!(
|
||||
"{}",
|
||||
t!("service.mod.race-condition-detected")
|
||||
),
|
||||
ErrorKind::Database,
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
.await
|
||||
.result?;
|
||||
handle_installed(s9pk).await
|
||||
}
|
||||
.await
|
||||
{
|
||||
Ok(service) => {
|
||||
crate::volume::remove_install_backup(id).await.log_err();
|
||||
Ok(service)
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!(
|
||||
"Update rollback failed for {id}, restoring volume snapshot: {e}"
|
||||
);
|
||||
crate::volume::restore_volumes_from_install_backup(id)
|
||||
.await
|
||||
.log_err();
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
PackageStateMatchModelRef::Removing(_) | PackageStateMatchModelRef::Restoring(_) => {
|
||||
if let Ok(s9pk) = S9pk::open(s9pk_path, Some(id)).await.map_err(|e| {
|
||||
|
||||
Reference in New Issue
Block a user