mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-27 02:41:53 +00:00
diagnostic mode changes
This commit is contained in:
@@ -2,12 +2,12 @@ use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
use embassy::context::rpc::RpcContextConfig;
|
||||
use embassy::context::{RecoveryContext, SetupContext};
|
||||
use embassy::context::{DiagnosticContext, SetupContext};
|
||||
use embassy::disk::main::DEFAULT_PASSWORD;
|
||||
use embassy::hostname::get_product_key;
|
||||
use embassy::middleware::cors::cors;
|
||||
use embassy::middleware::diagnostic::diagnostic;
|
||||
use embassy::middleware::encrypt::encrypt;
|
||||
use embassy::middleware::recovery::recovery;
|
||||
use embassy::net::mdns::MdnsController;
|
||||
use embassy::sound::MARIO_COIN;
|
||||
use embassy::util::Invoke;
|
||||
@@ -172,7 +172,7 @@ async fn inner_main(cfg_path: Option<&str>) -> Result<(), Error> {
|
||||
let mdns = MdnsController::init();
|
||||
tokio::fs::write(
|
||||
"/etc/nginx/sites-available/default",
|
||||
include_str!("../nginx/recovery-ui.conf"),
|
||||
include_str!("../nginx/diagnostic-ui.conf"),
|
||||
)
|
||||
.await
|
||||
.with_ctx(|_| {
|
||||
@@ -186,14 +186,14 @@ async fn inner_main(cfg_path: Option<&str>) -> Result<(), Error> {
|
||||
.arg("nginx")
|
||||
.invoke(embassy::ErrorKind::Nginx)
|
||||
.await?;
|
||||
let ctx = RecoveryContext::init(cfg_path, e).await?;
|
||||
let ctx = DiagnosticContext::init(cfg_path, e).await?;
|
||||
rpc_server!({
|
||||
command: embassy::recovery_api,
|
||||
command: embassy::diagnostic_api,
|
||||
context: ctx.clone(),
|
||||
status: status_fn,
|
||||
middleware: [
|
||||
cors,
|
||||
recovery,
|
||||
diagnostic,
|
||||
]
|
||||
})
|
||||
.with_graceful_shutdown({
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use embassy::context::{RecoveryContext, RpcContext};
|
||||
use embassy::context::{DiagnosticContext, RpcContext};
|
||||
use embassy::db::subscribe;
|
||||
use embassy::middleware::auth::auth;
|
||||
use embassy::middleware::cors::cors;
|
||||
use embassy::middleware::recovery::recovery;
|
||||
use embassy::middleware::diagnostic::diagnostic;
|
||||
use embassy::net::tor::tor_health_check;
|
||||
use embassy::shutdown::Shutdown;
|
||||
use embassy::status::{check_all, synchronize_all};
|
||||
@@ -275,14 +275,14 @@ fn main() {
|
||||
log::error!("{}", e.source);
|
||||
log::debug!("{}", e.source);
|
||||
embassy::sound::BEETHOVEN.play().await?;
|
||||
let ctx = RecoveryContext::init(cfg_path, e).await?;
|
||||
let ctx = DiagnosticContext::init(cfg_path, e).await?;
|
||||
rpc_server!({
|
||||
command: embassy::recovery_api,
|
||||
command: embassy::diagnostic_api,
|
||||
context: ctx.clone(),
|
||||
status: status_fn,
|
||||
middleware: [
|
||||
cors,
|
||||
recovery,
|
||||
diagnostic,
|
||||
]
|
||||
})
|
||||
.with_graceful_shutdown({
|
||||
|
||||
@@ -16,10 +16,10 @@ use crate::{Error, ResultExt};
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct RecoveryContextConfig {
|
||||
pub struct DiagnosticContextConfig {
|
||||
pub bind_rpc: Option<SocketAddr>,
|
||||
}
|
||||
impl RecoveryContextConfig {
|
||||
impl DiagnosticContextConfig {
|
||||
pub async fn load<P: AsRef<Path>>(path: Option<P>) -> Result<Self, Error> {
|
||||
let cfg_path = path
|
||||
.as_ref()
|
||||
@@ -36,21 +36,21 @@ impl RecoveryContextConfig {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RecoveryContextSeed {
|
||||
pub struct DiagnosticContextSeed {
|
||||
pub bind_rpc: SocketAddr,
|
||||
pub shutdown: Sender<()>,
|
||||
pub error: Arc<RpcError>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RecoveryContext(Arc<RecoveryContextSeed>);
|
||||
impl RecoveryContext {
|
||||
pub struct DiagnosticContext(Arc<DiagnosticContextSeed>);
|
||||
impl DiagnosticContext {
|
||||
pub async fn init<P: AsRef<Path>>(path: Option<P>, error: Error) -> Result<Self, Error> {
|
||||
let cfg = RecoveryContextConfig::load(path).await?;
|
||||
let cfg = DiagnosticContextConfig::load(path).await?;
|
||||
|
||||
let (shutdown, _) = tokio::sync::broadcast::channel(1);
|
||||
|
||||
Ok(Self(Arc::new(RecoveryContextSeed {
|
||||
Ok(Self(Arc::new(DiagnosticContextSeed {
|
||||
bind_rpc: cfg.bind_rpc.unwrap_or(([127, 0, 0, 1], 5959).into()),
|
||||
shutdown,
|
||||
error: Arc::new(error.into()),
|
||||
@@ -58,7 +58,7 @@ impl RecoveryContext {
|
||||
}
|
||||
}
|
||||
|
||||
impl Context for RecoveryContext {
|
||||
impl Context for DiagnosticContext {
|
||||
fn host(&self) -> Host<&str> {
|
||||
match self.0.bind_rpc.ip() {
|
||||
IpAddr::V4(a) => Host::Ipv4(a),
|
||||
@@ -69,8 +69,8 @@ impl Context for RecoveryContext {
|
||||
self.0.bind_rpc.port()
|
||||
}
|
||||
}
|
||||
impl Deref for RecoveryContext {
|
||||
type Target = RecoveryContextSeed;
|
||||
impl Deref for DiagnosticContext {
|
||||
type Target = DiagnosticContextSeed;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&*self.0
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
pub mod cli;
|
||||
pub mod recovery;
|
||||
pub mod diagnostic;
|
||||
pub mod rpc;
|
||||
pub mod setup;
|
||||
|
||||
pub use cli::CliContext;
|
||||
pub use recovery::RecoveryContext;
|
||||
pub use diagnostic::DiagnosticContext;
|
||||
pub use rpc::RpcContext;
|
||||
pub use setup::SetupContext;
|
||||
|
||||
@@ -13,8 +13,8 @@ impl From<CliContext> for () {
|
||||
()
|
||||
}
|
||||
}
|
||||
impl From<RecoveryContext> for () {
|
||||
fn from(_: RecoveryContext) -> Self {
|
||||
impl From<DiagnosticContext> for () {
|
||||
fn from(_: DiagnosticContext) -> Self {
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ impl Database {
|
||||
tor_address: format!("http://{}", tor_key.public().get_onion_address())
|
||||
.parse()
|
||||
.unwrap(),
|
||||
status: ServerStatus::Running,
|
||||
status: ServerStatus::Running {},
|
||||
eos_marketplace: "https://beta-registry-0-3.start9labs.com".parse().unwrap(),
|
||||
package_marketplace: None,
|
||||
wifi: WifiInfo {
|
||||
@@ -72,26 +72,38 @@ impl DatabaseModel {
|
||||
#[derive(Debug, Deserialize, Serialize, HasModel)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct ServerInfo {
|
||||
id: String,
|
||||
version: Version,
|
||||
lan_address: Url,
|
||||
tor_address: Url,
|
||||
status: ServerStatus,
|
||||
eos_marketplace: Url,
|
||||
package_marketplace: Option<Url>,
|
||||
wifi: WifiInfo,
|
||||
unread_notification_count: u64,
|
||||
specs: ServerSpecs,
|
||||
connection_addresses: ConnectionAddresses,
|
||||
share_stats: bool,
|
||||
pub id: String,
|
||||
pub version: Version,
|
||||
pub lan_address: Url,
|
||||
pub tor_address: Url,
|
||||
#[serde(flatten)]
|
||||
pub status: ServerStatus,
|
||||
pub eos_marketplace: Url,
|
||||
pub package_marketplace: Option<Url>,
|
||||
pub wifi: WifiInfo,
|
||||
pub unread_notification_count: u64,
|
||||
pub specs: ServerSpecs,
|
||||
pub connection_addresses: ConnectionAddresses,
|
||||
pub share_stats: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[serde(tag = "status")]
|
||||
pub enum ServerStatus {
|
||||
Running,
|
||||
Updating,
|
||||
BackingUp,
|
||||
Running {},
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
Updating {
|
||||
update_progress: UpdateProgress,
|
||||
},
|
||||
BackingUp {},
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct UpdateProgress {
|
||||
pub size: u64,
|
||||
pub downloaded: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::sync::Arc;
|
||||
use rpc_toolkit::command;
|
||||
use rpc_toolkit::yajrc::RpcError;
|
||||
|
||||
use crate::context::RecoveryContext;
|
||||
use crate::context::DiagnosticContext;
|
||||
use crate::logs::{display_logs, fetch_logs, LogResponse, LogSource};
|
||||
use crate::util::display_none;
|
||||
use crate::Error;
|
||||
@@ -11,12 +11,12 @@ use crate::Error;
|
||||
pub const SYSTEMD_UNIT: &'static str = "embassy-init";
|
||||
|
||||
#[command(subcommands(error, logs, exit))]
|
||||
pub fn recovery() -> Result<(), Error> {
|
||||
pub fn diagnostic() -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
pub fn error(#[context] ctx: RecoveryContext) -> Result<Arc<RpcError>, Error> {
|
||||
pub fn error(#[context] ctx: DiagnosticContext) -> Result<Arc<RpcError>, Error> {
|
||||
Ok(ctx.error.clone())
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ pub async fn logs(
|
||||
}
|
||||
|
||||
#[command(display(display_none))]
|
||||
pub fn exit(#[context] ctx: RecoveryContext) -> Result<(), Error> {
|
||||
pub fn exit(#[context] ctx: DiagnosticContext) -> Result<(), Error> {
|
||||
ctx.shutdown.send(()).expect("receiver dropped");
|
||||
Ok(())
|
||||
}
|
||||
@@ -8,6 +8,8 @@ use crate::{Error, ResultExt};
|
||||
pub const PASSWORD_PATH: &'static str = "/etc/embassy/password";
|
||||
pub const DEFAULT_PASSWORD: &'static str = "password";
|
||||
|
||||
// TODO: use IncorrectDisk / DiskNotAvailable / DiskCorrupted
|
||||
|
||||
pub async fn create<I: IntoIterator<Item = P>, P: AsRef<Path>>(
|
||||
pool_name: &str,
|
||||
disks: I,
|
||||
|
||||
@@ -20,17 +20,17 @@ pub enum ErrorKind {
|
||||
Deserialization = 12,
|
||||
Utf8 = 13,
|
||||
ParseVersion = 14,
|
||||
Duplicity = 15, // REMOVE
|
||||
IncorrectDisk = 15,
|
||||
Nginx = 16,
|
||||
Dependency = 17,
|
||||
ParseS9pk = 18,
|
||||
ParseUrl = 19,
|
||||
GParted = 20, // REMOVE
|
||||
DiskNotAvailable = 20,
|
||||
BlockDevice = 21,
|
||||
InvalidOnionAddress = 22,
|
||||
Pack = 23,
|
||||
ValidateS9pk = 24,
|
||||
OpenSSL = 25, // REMOVE
|
||||
DiskCorrupted = 25,
|
||||
Tor = 26,
|
||||
ConfigGen = 27,
|
||||
ParseNumber = 28,
|
||||
@@ -56,7 +56,7 @@ pub enum ErrorKind {
|
||||
Zfs = 48,
|
||||
OpenSsl = 49,
|
||||
PasswordHashGeneration = 50,
|
||||
RecoveryMode = 51,
|
||||
DiagnosticMode = 51,
|
||||
ParseDbField = 52,
|
||||
}
|
||||
impl ErrorKind {
|
||||
@@ -77,17 +77,17 @@ impl ErrorKind {
|
||||
Deserialization => "Deserialization Error",
|
||||
Utf8 => "UTF-8 Parse Error",
|
||||
ParseVersion => "Version Parsing Error",
|
||||
Duplicity => "Duplicity Error",
|
||||
IncorrectDisk => "Incorrect Disk",
|
||||
Nginx => "Nginx Error",
|
||||
Dependency => "Dependency Error",
|
||||
ParseS9pk => "S9PK Parsing Error",
|
||||
ParseUrl => "URL Parsing Error",
|
||||
GParted => "GNU Parted Error",
|
||||
DiskNotAvailable => "Disk Not Available",
|
||||
BlockDevice => "Block Device Error",
|
||||
InvalidOnionAddress => "Invalid Onion Address",
|
||||
Pack => "Pack Error",
|
||||
ValidateS9pk => "S9PK Validation Error",
|
||||
OpenSSL => "OpenSSL Error", // Remove
|
||||
DiskCorrupted => "Disk Corrupted", // Remove
|
||||
Tor => "Tor Daemon Error",
|
||||
ConfigGen => "Config Generation Error",
|
||||
ParseNumber => "Number Parsing Error",
|
||||
@@ -113,7 +113,7 @@ impl ErrorKind {
|
||||
Zfs => "ZFS Error",
|
||||
OpenSsl => "OpenSSL Internal Error",
|
||||
PasswordHashGeneration => "Password Hash Generation Error",
|
||||
RecoveryMode => "Embassy is in Recovery Mode",
|
||||
DiagnosticMode => "Embassy is in Diagnostic Mode",
|
||||
ParseDbField => "Database Field Parse Error",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ pub mod control;
|
||||
pub mod db;
|
||||
pub mod dependencies;
|
||||
pub mod developer;
|
||||
pub mod diagnostic;
|
||||
pub mod disk;
|
||||
pub mod error;
|
||||
pub mod hostname;
|
||||
@@ -28,7 +29,6 @@ pub mod migration;
|
||||
pub mod net;
|
||||
pub mod notifications;
|
||||
pub mod properties;
|
||||
pub mod recovery;
|
||||
pub mod s9pk;
|
||||
pub mod setup;
|
||||
pub mod shutdown;
|
||||
@@ -106,8 +106,8 @@ pub fn portable_api() -> Result<(), RpcError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command(subcommands(version::git_info, echo, recovery::recovery))]
|
||||
pub fn recovery_api() -> Result<(), RpcError> {
|
||||
#[command(subcommands(version::git_info, echo, diagnostic::diagnostic))]
|
||||
pub fn diagnostic_api() -> Result<(), RpcError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use rpc_toolkit::Metadata;
|
||||
|
||||
use crate::Error;
|
||||
|
||||
pub async fn recovery<M: Metadata>(
|
||||
pub async fn diagnostic<M: Metadata>(
|
||||
_req: &mut Request<Body>,
|
||||
_metadata: M,
|
||||
) -> Result<Result<DynMiddlewareStage2, Response<Body>>, HttpError> {
|
||||
@@ -19,8 +19,11 @@ pub async fn recovery<M: Metadata>(
|
||||
if let Err(e) = rpc_res {
|
||||
if e.code == -32601 {
|
||||
*e = Error::new(
|
||||
anyhow::anyhow!("{} is not available on the Recovery API", method),
|
||||
crate::ErrorKind::RecoveryMode,
|
||||
anyhow::anyhow!(
|
||||
"{} is not available on the Diagnostic API",
|
||||
method
|
||||
),
|
||||
crate::ErrorKind::DiagnosticMode,
|
||||
)
|
||||
.into();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
pub mod auth;
|
||||
pub mod cors;
|
||||
pub mod diagnostic;
|
||||
pub mod encrypt;
|
||||
pub mod recovery;
|
||||
|
||||
@@ -2,7 +2,7 @@ server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
|
||||
root /var/www/html/recovery;
|
||||
root /var/www/html/diagnostic;
|
||||
|
||||
index index.html index.htm index.nginx-debian.html;
|
||||
|
||||
Reference in New Issue
Block a user