mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
feat: Make the start clear
Have messaging to let user know of update complete/ failure
This commit is contained in:
committed by
Aiden McClelland
parent
2b2451d22f
commit
7fc4cb175c
3
Makefile
3
Makefile
@@ -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)
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ pub struct ServerInfo {
|
||||
pub enum ServerStatus {
|
||||
Running,
|
||||
Updating,
|
||||
Updated,
|
||||
BackingUp,
|
||||
}
|
||||
|
||||
|
||||
@@ -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: _,
|
||||
|
||||
@@ -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;
|
||||
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(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user