feat: For ota update using rsyncd (#1938)

* feat: For ota update using rsyncd

* chore: Fix where we rsync to.

* chore: Getting rsync to work

* chore: Add in the is raspberry pi

* chore: Update is raspberry pi
This commit is contained in:
J M
2022-11-15 13:44:53 -07:00
committed by Aiden McClelland
parent 54749dfd1e
commit 5b91b5f436
8 changed files with 255 additions and 50 deletions

View File

@@ -8,6 +8,9 @@ lazy_static::lazy_static! {
let (arch, _) = TARGET.split_once("-").unwrap();
arch
};
pub static ref IS_RASPBERRY_PI: bool = {
*ARCH == "aarch64"
};
}
pub mod action;

View File

@@ -18,7 +18,7 @@ pub fn host_addr_fqdn(req: &Request<Body>) -> Result<ResourceFqdn, Error> {
.map_err(|e| Error::new(eyre!("{}", e), crate::ErrorKind::AsciiError))?
.to_string();
let host_uri: ResourceFqdn = host_str.parse()?;
let host_uri: ResourceFqdn = host_str.split(':').next().unwrap().parse()?;
Ok(host_uri)
}
@@ -35,7 +35,7 @@ pub enum ResourceFqdn {
root: String,
tld: Tld,
},
LocalHost
LocalHost,
}
impl fmt::Display for ResourceFqdn {
@@ -51,7 +51,7 @@ impl fmt::Display for ResourceFqdn {
} => {
write!(f, "{}", full_uri)
}
ResourceFqdn::LocalHost => write!(f, "localhost")
ResourceFqdn::LocalHost => write!(f, "localhost"),
}
}
}
@@ -77,11 +77,10 @@ impl FromStr for ResourceFqdn {
type Err = Error;
fn from_str(input: &str) -> Result<ResourceFqdn, Self::Err> {
if input == "localhost" {
return Ok(ResourceFqdn::LocalHost);
}
if let Ok(ip) = input.parse::<IpAddr>() {
return Ok(ResourceFqdn::IpAddr(ip));
}

View File

@@ -1,3 +1,4 @@
use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
@@ -16,11 +17,8 @@ use tracing::instrument;
use crate::context::RpcContext;
use crate::db::model::UpdateProgress;
use crate::disk::mount::filesystem::bind::Bind;
use crate::disk::mount::filesystem::block_dev::BlockDev;
use crate::disk::mount::filesystem::httpdirfs::HttpDirFS;
use crate::disk::mount::filesystem::ReadOnly;
use crate::disk::mount::filesystem::ReadWrite;
use crate::disk::mount::guard::{MountGuard, TmpMountGuard};
use crate::disk::mount::guard::MountGuard;
use crate::notifications::NotificationLevel;
use crate::sound::{
CIRCLE_OF_5THS_SHORT, UPDATE_FAILED_1, UPDATE_FAILED_2, UPDATE_FAILED_3, UPDATE_FAILED_4,
@@ -29,7 +27,7 @@ use crate::update::latest_information::LatestInformation;
use crate::util::Invoke;
use crate::version::{Current, VersionT};
use crate::{Error, ErrorKind, ResultExt};
use crate::{Error, ErrorKind, ResultExt, IS_RASPBERRY_PI};
mod latest_information;
@@ -131,23 +129,10 @@ async fn maybe_do_update(
// validate (hash) fs
// kernel update?
// swap selected fs
let new_block_dev = TmpMountGuard::mount(
&HttpDirFS::new(
EosUrl {
base: marketplace_url,
version: latest_version,
}
.to_string()
.parse()?,
),
ReadOnly,
)
.await?;
let new_fs = TmpMountGuard::mount(
&BlockDev::new(new_block_dev.as_ref().join("eos.img")),
ReadOnly,
)
.await?;
let eos_url = EosUrl {
base: marketplace_url,
version: latest_version,
};
status.update_progress = Some(UpdateProgress {
size: Some(100),
@@ -157,7 +142,7 @@ async fn maybe_do_update(
let rev = tx.commit().await?;
tokio::spawn(async move {
let res = do_update(ctx.clone(), new_fs, new_block_dev).await;
let res = do_update(ctx.clone(), eos_url).await;
let mut db = ctx.db.handle();
let mut status = crate::db::DatabaseModel::new()
.server_info()
@@ -212,14 +197,10 @@ async fn maybe_do_update(
Ok(rev)
}
#[instrument(skip(ctx, new_fs, new_block_dev))]
async fn do_update(
ctx: RpcContext,
new_fs: TmpMountGuard,
new_block_dev: TmpMountGuard,
) -> Result<(), Error> {
#[instrument(skip(ctx, eos_url))]
async fn do_update(ctx: RpcContext, eos_url: EosUrl) -> Result<(), Error> {
let mut rsync = Rsync::new(
new_fs.as_ref().join(""),
eos_url.rsync_path()?,
"/media/embassy/next",
Default::default(),
)?;
@@ -238,8 +219,6 @@ async fn do_update(
.await?;
}
rsync.wait().await?;
new_fs.unmount().await?;
new_block_dev.unmount().await?;
copy_fstab().await?;
copy_machine_id().await?;
@@ -255,16 +234,23 @@ struct EosUrl {
base: Url,
version: Version,
}
impl std::fmt::Display for EosUrl {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}/eos/v0/eos.img?spec=={}&eos-version={}&arch={}",
self.base,
self.version,
Current::new().semver(),
&*crate::ARCH,
)
impl EosUrl {
#[instrument()]
pub fn rsync_path(&self) -> Result<PathBuf, Error> {
let host = self
.base
.host_str()
.ok_or_else(|| Error::new(eyre!("Could not get host of base"), ErrorKind::ParseUrl))?;
let version: &Version = &self.version;
let arch = if *IS_RASPBERRY_PI {
"raspberry_pi"
} else {
*crate::ARCH
};
Ok(format!("{host}::{version}/{arch}/")
.parse()
.map_err(|e| Error::new(eyre!("Could not parse path"), ErrorKind::ParseUrl))?)
}
}