feat: Make the start clear

Have messaging to let user know of update complete/ failure
This commit is contained in:
Justin Miller
2021-10-09 15:24:01 -06:00
committed by Aiden McClelland
parent 2b2451d22f
commit 7fc4cb175c
5 changed files with 78 additions and 22 deletions

View File

@@ -6,7 +6,7 @@ APPMGR_SRC := $(shell find appmgr/src) appmgr/Cargo.toml appmgr/Cargo.lock
UI_SRC := $(shell find ui/src)
SETUP_WIZARD_SRC := $(shell find setup-wizard/src)
DIAGNOSTIC_UI_SRC := $(shell find diagnostic-ui/src)
PATCH_DB_CLIENT_SRC = $(shell find patch-db/client)
PATCH_DB_CLIENT_SRC = $(shell find patch-db/client -not -path patch-db/client/dist)
all: eos.img
@@ -71,6 +71,7 @@ patch-db/client/node_modules: patch-db/client/package.json
npm --prefix patch-db/client install
patch-db/client/dist: $(PATCH_DB_CLIENT_SRC) patch-db/client/node_modules
! test -d patch-db/client/dist || rm -rf patch-db/client/dist
npm --prefix patch-db/client run build
ui: $(EMBASSY_UIS)

View File

@@ -3,6 +3,8 @@ use std::sync::Arc;
use embassy::context::rpc::RpcContextConfig;
use embassy::context::{DiagnosticContext, SetupContext};
use embassy::db::model::ServerStatus;
use embassy::db::DatabaseModel;
use embassy::disk::main::DEFAULT_PASSWORD;
use embassy::hostname::get_product_key;
use embassy::middleware::cors::cors;
@@ -11,7 +13,7 @@ use embassy::middleware::encrypt::encrypt;
#[cfg(feature = "avahi")]
use embassy::net::mdns::MdnsController;
use embassy::sound::MARIO_COIN;
use embassy::util::Invoke;
use embassy::util::{Invoke, Version};
use embassy::{Error, ResultExt};
use http::StatusCode;
use rpc_toolkit::rpc_server;
@@ -144,6 +146,25 @@ async fn init(cfg_path: Option<&str>) -> Result<(), Error> {
log::info!("Enabled nginx public dir");
embassy::net::wifi::synchronize_wpa_supplicant_conf(&cfg.datadir().join("main")).await?;
let db = cfg.db(&secret_store).await?;
let mut handle = db.handle();
let mut info = embassy::db::DatabaseModel::new()
.server_info()
.get_mut(&mut handle)
.await?;
match info.status {
ServerStatus::Running | ServerStatus::Updated | ServerStatus::BackingUp => {
info.status = ServerStatus::Running;
}
ServerStatus::Updating => {
info.update_progress = None;
info.status = ServerStatus::Running;
}
}
info.version = emver::Version::new(0, 3, 0, 0).into();
// TODO: run migrations
info.save(&mut handle).await?;
Ok(())
}

View File

@@ -88,6 +88,7 @@ pub struct ServerInfo {
pub enum ServerStatus {
Running,
Updating,
Updated,
BackingUp,
}

View File

@@ -213,9 +213,9 @@ pub enum NotificationSubtype {
}
impl NotificationSubtype {
fn to_json(&self) -> serde_json::Value {
match &self {
&NotificationSubtype::General => serde_json::Value::Null,
&NotificationSubtype::BackupReport {
match self {
NotificationSubtype::General => serde_json::Value::Null,
NotificationSubtype::BackupReport {
server_attempted,
server_error,
packages,
@@ -241,9 +241,9 @@ impl NotificationSubtype {
}
}
fn code(&self) -> u32 {
match &self {
&Self::General => 0,
&Self::BackupReport {
match self {
Self::General => 0,
Self::BackupReport {
server_attempted: _,
server_error: _,
packages: _,

View File

@@ -1,8 +1,9 @@
use std::future::Future;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::Duration;
use anyhow::{anyhow, bail, Result};
use anyhow::{anyhow, Result};
use clap::ArgMatches;
use digest::Digest;
use emver::Version;
@@ -13,21 +14,31 @@ use regex::Regex;
use reqwest::Url;
use rpc_toolkit::command;
use sha2::Sha256;
use std::sync::atomic::{AtomicBool, Ordering};
use tokio::io::AsyncWriteExt;
use tokio::pin;
use tokio::process::Command;
use tokio::time::Instant;
use tokio_stream::StreamExt;
use crate::context::RpcContext;
use crate::db::model::{ServerStatus, UpdateProgress};
use crate::notifications::{NotificationLevel, NotificationSubtype};
use crate::update::latest_information::LatestInformation;
use crate::util::Invoke;
use crate::{Error, ErrorKind, ResultExt};
lazy_static! {
static ref UPDATED: AtomicBool = AtomicBool::new(false);
}
/// An user/ daemon would call this to update the system to the latest version and do the updates available,
/// and this will return something if there is an update, and in that case there will need to be a restart.
#[command(rename = "update", display(display_properties))]
pub async fn update_system(#[context] ctx: RpcContext) -> Result<UpdateSystem, Error> {
if UPDATED.load(Ordering::SeqCst) {
return Ok(UpdateSystem::NoUpdates);
}
if let None = maybe_do_update(ctx).await? {
return Ok(UpdateSystem::Updated);
}
@@ -52,7 +63,7 @@ fn display_properties(status: UpdateSystem, _: &ArgMatches<'_>) {
}
}
const HEADER_KEY: &str = "CHECKSUM";
const HEADER_KEY: &str = "x-eos-hash";
mod latest_information;
#[derive(Debug, Clone, Copy)]
@@ -170,13 +181,16 @@ async fn maybe_do_update(ctx: RpcContext) -> Result<Option<Arc<Revision>>, Error
.get_mut(&mut tx)
.await?;
match &info.status {
ServerStatus::Updating { .. } => {
ServerStatus::Updating => {
return Err(Error::new(
anyhow!("Server is already updating!"),
crate::ErrorKind::InvalidRequest,
))
}
ServerStatus::BackingUp {} => {
ServerStatus::Updated => {
return Ok(None);
}
ServerStatus::BackingUp => {
return Err(Error::new(
anyhow!("Server is backing up!"),
crate::ErrorKind::InvalidRequest,
@@ -191,7 +205,7 @@ async fn maybe_do_update(ctx: RpcContext) -> Result<Option<Arc<Revision>>, Error
ctx.db.handle(),
&EosUrl {
base: info.eos_marketplace.clone(),
version: latest_version,
version: latest_version.clone(),
},
new_label,
)
@@ -212,13 +226,26 @@ async fn maybe_do_update(ctx: RpcContext) -> Result<Option<Arc<Revision>>, Error
.get_mut(&mut db)
.await
.expect("could not access status");
info.status = ServerStatus::Running;
info.update_progress = None;
info.save(&mut db).await.expect("could not save status");
match res {
Ok(()) => todo!("issue notification"),
Ok(()) => {
info.status = ServerStatus::Updated;
info.save(&mut db).await.expect("could not save status");
}
Err(e) => {
todo!("{}, issue notification", e)
info.status = ServerStatus::Running;
info.save(&mut db).await.expect("could not save status");
drop(db);
ctx.notification_manager
.notify(
None,
NotificationLevel::Error,
"EmbassyOS Update Failed".to_owned(),
format!("Update was not successful because of {}", e),
NotificationSubtype::General,
)
.await
.expect("")
}
}
});
@@ -321,16 +348,20 @@ async fn write_stream_to_label<Db: DbHandle>(
let mut hasher = Sha256::new();
pin!(stream_download);
let mut downloaded = 0;
let mut last_progress_update = Instant::now();
while let Some(Ok(item)) = stream_download.next().await {
file.write_all(&item)
.await
.with_kind(ErrorKind::Filesystem)?;
downloaded += item.len() as u64;
crate::db::DatabaseModel::new()
.server_info()
.update_progress()
.put(db, &UpdateProgress { size, downloaded })
.await?;
if last_progress_update.elapsed() > Duration::from_secs(1) {
last_progress_update = Instant::now();
crate::db::DatabaseModel::new()
.server_info()
.update_progress()
.put(db, &UpdateProgress { size, downloaded })
.await?;
}
hasher.update(item);
}
file.flush().await.with_kind(ErrorKind::Filesystem)?;
@@ -373,6 +404,8 @@ async fn swap_boot_label(
.arg(mounted_boot.value.mount_folder().join("cmdline.txt"))
.output()
.await?;
UPDATED.store(true, Ordering::SeqCst);
Ok(())
}