Files
start-os/backend/src/migration.rs
Aiden McClelland 6ad9a5952e Feature/multi platform (#1866)
* wip

* wip

* wip

* wip

* wip

* wip

* remove debian dir

* lazy env and git hash

* remove env and git hash on clean

* don't leave project dir

* use docker for native builds

* start9 rust

* correctly mount registry

* remove systemd config

* switch to /usr/bin

* disable sound for now

* wip

* change disk list

* multi-arch images

* multi-arch system images

* default aarch64

* edition 2021

* dynamic wifi interface name

* use wifi interface from config

* bugfixes

* add beep based sound

* wip

* wip

* wip

* separate out raspberry pi specific files

* fixes

* use new initramfs always

* switch journald conf to sed script

* fixes

* fix permissions

* talking about kernel modules not scripts

* fix

* fix

* switch to MBR

* install to /usr/lib

* fixes

* fixes

* fixes

* fixes

* add media config to cfg path

* fixes

* fixes

* fixes

* raspi image fixes

* fix test

* fix workflow

* sync boot partition

* gahhhhh
2022-11-29 09:43:54 -07:00

140 lines
4.3 KiB
Rust

use std::collections::BTreeSet;
use color_eyre::eyre::eyre;
use emver::VersionRange;
use futures::{Future, FutureExt};
use indexmap::IndexMap;
use patch_db::HasModel;
use serde::{Deserialize, Serialize};
use tracing::instrument;
use crate::context::RpcContext;
use crate::id::ImageId;
use crate::procedure::docker::DockerContainer;
use crate::procedure::{PackageProcedure, ProcedureName};
use crate::s9pk::manifest::PackageId;
use crate::util::Version;
use crate::volume::Volumes;
use crate::{Error, ResultExt};
#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)]
#[serde(rename_all = "kebab-case")]
pub struct Migrations {
pub from: IndexMap<VersionRange, PackageProcedure>,
pub to: IndexMap<VersionRange, PackageProcedure>,
}
impl Migrations {
#[instrument]
pub fn validate(
&self,
container: &Option<DockerContainer>,
eos_version: &Version,
volumes: &Volumes,
image_ids: &BTreeSet<ImageId>,
) -> Result<(), Error> {
for (version, migration) in &self.from {
migration
.validate(container, eos_version, volumes, image_ids, true)
.with_ctx(|_| {
(
crate::ErrorKind::ValidateS9pk,
format!("Migration from {}", version),
)
})?;
}
for (version, migration) in &self.to {
migration
.validate(container, eos_version, volumes, image_ids, true)
.with_ctx(|_| {
(
crate::ErrorKind::ValidateS9pk,
format!("Migration to {}", version),
)
})?;
}
Ok(())
}
#[instrument(skip(ctx))]
pub fn from<'a>(
&'a self,
container: &'a Option<DockerContainer>,
ctx: &'a RpcContext,
version: &'a Version,
pkg_id: &'a PackageId,
pkg_version: &'a Version,
volumes: &'a Volumes,
) -> Option<impl Future<Output = Result<MigrationRes, Error>> + 'a> {
if let Some((_, migration)) = self
.from
.iter()
.find(|(range, _)| version.satisfies(*range))
{
Some(
migration
.execute(
ctx,
container,
pkg_id,
pkg_version,
ProcedureName::Migration, // Migrations cannot be executed concurrently
volumes,
Some(version),
None,
)
.map(|r| {
r.and_then(|r| {
r.map_err(|e| {
Error::new(eyre!("{}", e.1), crate::ErrorKind::MigrationFailed)
})
})
}),
)
} else {
None
}
}
#[instrument(skip(ctx))]
pub fn to<'a>(
&'a self,
container: &'a Option<DockerContainer>,
ctx: &'a RpcContext,
version: &'a Version,
pkg_id: &'a PackageId,
pkg_version: &'a Version,
volumes: &'a Volumes,
) -> Option<impl Future<Output = Result<MigrationRes, Error>> + 'a> {
if let Some((_, migration)) = self.to.iter().find(|(range, _)| version.satisfies(*range)) {
Some(
migration
.execute(
ctx,
container,
pkg_id,
pkg_version,
ProcedureName::Migration,
volumes,
Some(version),
None,
)
.map(|r| {
r.and_then(|r| {
r.map_err(|e| {
Error::new(eyre!("{}", e.1), crate::ErrorKind::MigrationFailed)
})
})
}),
)
} else {
None
}
}
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)]
#[serde(rename_all = "kebab-case")]
pub struct MigrationRes {
pub configured: bool,
}