diagnostic mode changes

This commit is contained in:
Aiden McClelland
2021-09-15 12:03:29 -06:00
parent 14c7540738
commit 2fd97b323c
12 changed files with 78 additions and 61 deletions

View File

@@ -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({

View File

@@ -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({

View File

@@ -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
}

View File

@@ -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 {
()
}
}

View File

@@ -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)]

View File

@@ -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(())
}

View File

@@ -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,

View File

@@ -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",
}
}

View File

@@ -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(())
}

View File

@@ -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();
}

View File

@@ -1,4 +1,4 @@
pub mod auth;
pub mod cors;
pub mod diagnostic;
pub mod encrypt;
pub mod recovery;

View File

@@ -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;