diff --git a/core/Cargo.lock b/core/Cargo.lock index c674ed77f..5c5f3e945 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -4964,7 +4964,7 @@ dependencies = [ [[package]] name = "start-os" -version = "0.3.5" +version = "0.3.5-rev.1" dependencies = [ "aes", "async-compression", diff --git a/core/startos/Cargo.toml b/core/startos/Cargo.toml index e371561d7..65c5dba98 100644 --- a/core/startos/Cargo.toml +++ b/core/startos/Cargo.toml @@ -14,7 +14,7 @@ keywords = [ name = "start-os" readme = "README.md" repository = "https://github.com/Start9Labs/start-os" -version = "0.3.5" +version = "0.3.5-rev.1" license = "MIT" [lib] diff --git a/core/startos/src/bins/mod.rs b/core/startos/src/bins/mod.rs index c391338fe..f9c88cae9 100644 --- a/core/startos/src/bins/mod.rs +++ b/core/startos/src/bins/mod.rs @@ -18,7 +18,7 @@ fn select_executable(name: &str) -> Option { match name { #[cfg(feature = "avahi-alias")] "avahi-alias" => Some(avahi_alias::main), - #[cfg(feature = "js_engine")] + #[cfg(feature = "js-engine")] "start-deno" => Some(start_deno::main), #[cfg(feature = "cli")] "start-cli" => Some(start_cli::main), @@ -36,24 +36,14 @@ fn select_executable(name: &str) -> Option { pub fn startbox() { let args = std::env::args().take(2).collect::>(); - if let Some(x) = args + let executable = args .get(0) .and_then(|s| Path::new(&*s).file_name()) - .and_then(|s| s.to_str()) - .and_then(|s| select_executable(&s)) - { - x() - } else if let Some(x) = args.get(1).and_then(|s| select_executable(&s)) { + .and_then(|s| s.to_str()); + if let Some(x) = executable.and_then(|s| select_executable(&s)) { x() } else { - eprintln!( - "unknown executable: {}", - args.get(0) - .filter(|x| &**x != "startbox") - .or_else(|| args.get(1)) - .map(|s| s.as_str()) - .unwrap_or("N/A") - ); + eprintln!("unknown executable: {}", executable.unwrap_or("N/A")); std::process::exit(1); } } diff --git a/core/startos/src/bins/start_init.rs b/core/startos/src/bins/start_init.rs index f189c3723..bafde4c74 100644 --- a/core/startos/src/bins/start_init.rs +++ b/core/startos/src/bins/start_init.rs @@ -3,6 +3,7 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use std::time::Duration; +use helpers::NonDetachingJoinHandle; use tokio::process::Command; use tracing::instrument; @@ -15,12 +16,20 @@ use crate::firmware::update_firmware; use crate::init::STANDBY_MODE_PATH; use crate::net::web_server::WebServer; use crate::shutdown::Shutdown; -use crate::sound::CHIME; +use crate::sound::{BEP, CHIME}; use crate::util::Invoke; use crate::{Error, ErrorKind, ResultExt, PLATFORM}; #[instrument(skip_all)] async fn setup_or_init(cfg_path: Option) -> Result, Error> { + let song = NonDetachingJoinHandle::from(tokio::spawn(async { + loop { + BEP.play().await.unwrap(); + BEP.play().await.unwrap(); + tokio::time::sleep(Duration::from_secs(30)).await; + } + })); + if update_firmware().await?.0 { return Ok(Some(Shutdown { export_args: None, @@ -74,6 +83,7 @@ async fn setup_or_init(cfg_path: Option) -> Result, Er ) .await?; + drop(song); tokio::time::sleep(Duration::from_secs(1)).await; // let the record state that I hate this CHIME.play().await?; @@ -100,8 +110,10 @@ async fn setup_or_init(cfg_path: Option) -> Result, Er ) .await?; + drop(song); tokio::time::sleep(Duration::from_secs(1)).await; // let the record state that I hate this CHIME.play().await?; + ctx.shutdown .subscribe() .recv() @@ -152,6 +164,7 @@ async fn setup_or_init(cfg_path: Option) -> Result, Er } tracing::info!("Loaded Disk"); crate::init::init(&cfg).await?; + drop(song); } Ok(None) diff --git a/core/startos/src/db/model.rs b/core/startos/src/db/model.rs index 15d404d49..9bfe90d61 100644 --- a/core/startos/src/db/model.rs +++ b/core/startos/src/db/model.rs @@ -23,6 +23,7 @@ use crate::net::utils::{get_iface_ipv4_addr, get_iface_ipv6_addr}; use crate::prelude::*; use crate::s9pk::manifest::{Manifest, PackageId}; use crate::status::Status; +use crate::util::cpupower::{get_preferred_governor, Governor}; use crate::util::Version; use crate::version::{Current, VersionT}; use crate::{ARCH, PLATFORM}; @@ -85,6 +86,7 @@ impl Database { .join(":"), ntp_synced: false, zram: true, + governor: None, }, package_data: AllPackageData::default(), lan_port_forwards: LanPortForwards::new(), @@ -137,6 +139,7 @@ pub struct ServerInfo { pub ntp_synced: bool, #[serde(default)] pub zram: bool, + pub governor: Option, } #[derive(Debug, Deserialize, Serialize, HasModel)] diff --git a/core/startos/src/init.rs b/core/startos/src/init.rs index 288149f37..e5accb992 100644 --- a/core/startos/src/init.rs +++ b/core/startos/src/init.rs @@ -20,7 +20,7 @@ use crate::middleware::auth::LOCAL_AUTH_COOKIE_PATH; use crate::prelude::*; use crate::sound::BEP; use crate::util::cpupower::{ - current_governor, get_available_governors, set_governor, GOVERNOR_PERFORMANCE, + current_governor, get_available_governors, get_preferred_governor, set_governor, }; use crate::util::docker::{create_bridge_network, CONTAINER_DATADIR, CONTAINER_TOOL}; use crate::util::Invoke; @@ -230,18 +230,6 @@ pub async fn init(cfg: &RpcContextConfig) -> Result { || &*server_info.version < &emver::Version::new(0, 3, 2, 0) || (*ARCH == "x86_64" && &*server_info.version < &emver::Version::new(0, 3, 4, 0)); - let song = if should_rebuild { - Some(NonDetachingJoinHandle::from(tokio::spawn(async { - loop { - BEP.play().await.unwrap(); - BEP.play().await.unwrap(); - tokio::time::sleep(Duration::from_secs(60)).await; - } - }))) - } else { - None - }; - let log_dir = cfg.datadir().join("main/logs"); if tokio::fs::metadata(&log_dir).await.is_err() { tokio::fs::create_dir_all(&log_dir).await?; @@ -354,21 +342,20 @@ pub async fn init(cfg: &RpcContextConfig) -> Result { .await?; tracing::info!("Enabled Docker QEMU Emulation"); - if current_governor() - .await? - .map(|g| &g != &GOVERNOR_PERFORMANCE) - .unwrap_or(false) - { - tracing::info!("Setting CPU Governor to \"{}\"", GOVERNOR_PERFORMANCE); - if get_available_governors() - .await? - .contains(&GOVERNOR_PERFORMANCE) - { - set_governor(&GOVERNOR_PERFORMANCE).await?; - tracing::info!("Set CPU Governor"); + let governor = if let Some(governor) = &server_info.governor { + if get_available_governors().await?.contains(governor) { + Some(governor) } else { - tracing::warn!("CPU Governor \"{}\" Not Available", GOVERNOR_PERFORMANCE) + tracing::warn!("CPU Governor \"{governor}\" Not Available"); + None } + } else { + get_preferred_governor().await? + }; + if let Some(governor) = governor { + tracing::info!("Setting CPU Governor to \"{governor}\""); + set_governor(governor).await?; + tracing::info!("Set CPU Governor"); } let mut time_not_synced = true; @@ -447,8 +434,6 @@ pub async fn init(cfg: &RpcContextConfig) -> Result { }?; } - drop(song); - tracing::info!("System initialized."); Ok(InitResult { secret_store, db }) diff --git a/core/startos/src/lib.rs b/core/startos/src/lib.rs index 141ef1780..5dac1f628 100644 --- a/core/startos/src/lib.rs +++ b/core/startos/src/lib.rs @@ -1,5 +1,3 @@ -#![recursion_limit = "256"] - pub const DEFAULT_MARKETPLACE: &str = "https://registry.start9.com"; // pub const COMMUNITY_MARKETPLACE: &str = "https://community-registry.start9.com"; pub const BUFFER_SIZE: usize = 1024; diff --git a/core/startos/src/procedure/js_scripts.rs b/core/startos/src/procedure/js_scripts.rs index 659e6a62c..f732458bb 100644 --- a/core/startos/src/procedure/js_scripts.rs +++ b/core/startos/src/procedure/js_scripts.rs @@ -225,18 +225,18 @@ async fn test_start_deno_command() -> Result { .arg("build") .invoke(ErrorKind::Unknown) .await?; - if tokio::fs::metadata("target/debug/start-deno") + if tokio::fs::metadata("../target/debug/start-deno") .await .is_err() { Command::new("ln") .arg("-rsf") - .arg("target/debug/startbox") - .arg("target/debug/start-deno") + .arg("../target/debug/startbox") + .arg("../target/debug/start-deno") .invoke(crate::ErrorKind::Filesystem) .await?; } - Ok(Command::new("target/debug/start-deno")) + Ok(Command::new("../target/debug/start-deno")) } #[cfg(test)] diff --git a/core/startos/src/system.rs b/core/startos/src/system.rs index 53216f796..b5cd42844 100644 --- a/core/startos/src/system.rs +++ b/core/startos/src/system.rs @@ -1,3 +1,4 @@ +use std::collections::BTreeSet; use std::fmt; use chrono::Utc; @@ -20,11 +21,12 @@ use crate::logs::{ }; use crate::prelude::*; use crate::shutdown::Shutdown; +use crate::util::cpupower::{get_available_governors, set_governor, Governor}; use crate::util::serde::{display_serializable, IoFormat}; use crate::util::{display_none, Invoke}; use crate::{Error, ErrorKind, ResultExt}; -#[command(subcommands(zram))] +#[command(subcommands(zram, governor))] pub async fn experimental() -> Result<(), Error> { Ok(()) } @@ -85,6 +87,56 @@ pub async fn zram(#[context] ctx: RpcContext, #[arg] enable: bool) -> Result<(), Ok(()) } +#[derive(Debug, Deserialize, Serialize)] +pub struct GovernorInfo { + current: Option, + available: BTreeSet, +} + +fn display_governor_info(arg: GovernorInfo, matches: &ArgMatches) { + use prettytable::*; + + if matches.is_present("format") { + return display_serializable(arg, matches); + } + + let mut table = Table::new(); + table.add_row(row![bc -> "GOVERNORS"]); + for entry in arg.available { + if Some(&entry) == arg.current.as_ref() { + table.add_row(row![g -> format!("* {entry} (current)")]); + } else { + table.add_row(row![entry]); + } + } + table.print_tty(false).unwrap(); +} + +#[command(display(display_governor_info))] +pub async fn governor( + #[context] ctx: RpcContext, + #[allow(unused_variables)] + #[arg(long = "format")] + format: Option, + #[arg] set: Option, +) -> Result { + let available = get_available_governors().await?; + if let Some(set) = set { + if !available.contains(&set) { + return Err(Error::new( + eyre!("Governor {set} not available"), + ErrorKind::InvalidRequest, + )); + } + set_governor(&set).await?; + ctx.db + .mutate(|d| d.as_server_info_mut().as_governor_mut().ser(&Some(set))) + .await?; + } + let current = ctx.db.peek().await.as_server_info().as_governor().de()?; + Ok(GovernorInfo { current, available }) +} + #[derive(Serialize, Deserialize)] pub struct TimeInfo { now: String, diff --git a/core/startos/src/util/cpupower.rs b/core/startos/src/util/cpupower.rs index a48502754..cc4ac5ef4 100644 --- a/core/startos/src/util/cpupower.rs +++ b/core/startos/src/util/cpupower.rs @@ -7,10 +7,20 @@ use tokio::process::Command; use crate::prelude::*; use crate::util::Invoke; -pub const GOVERNOR_PERFORMANCE: Governor = Governor(Cow::Borrowed("performance")); +pub const GOVERNOR_HEIRARCHY: &[Governor] = &[ + Governor(Cow::Borrowed("ondemand")), + Governor(Cow::Borrowed("schedutil")), + Governor(Cow::Borrowed("conservative")), +]; -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)] pub struct Governor(Cow<'static, str>); +impl std::str::FromStr for Governor { + type Err = std::convert::Infallible; + fn from_str(s: &str) -> Result { + Ok(Self(s.to_owned().into())) + } +} impl std::fmt::Display for Governor { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.0.fmt(f) @@ -29,13 +39,12 @@ impl std::borrow::Borrow for Governor { } pub async fn get_available_governors() -> Result, Error> { - let raw = String::from_utf8( - Command::new("cpupower") - .arg("frequency-info") - .arg("-g") - .invoke(ErrorKind::CpuSettings) - .await?, - )?; + let raw = Command::new("cpupower") + .arg("frequency-info") + .arg("-g") + .invoke(ErrorKind::CpuSettings) + .await + .map_or_else(|e| Ok(e.source.to_string()), String::from_utf8)?; let mut for_cpu: OrdMap> = OrdMap::new(); let mut current_cpu = None; for line in raw.lines() { @@ -114,6 +123,16 @@ pub async fn current_governor() -> Result, Error> { )) } +pub async fn get_preferred_governor() -> Result, Error> { + let governors = get_available_governors().await?; + for governor in GOVERNOR_HEIRARCHY { + if governors.contains(governor) { + return Ok(Some(governor)); + } + } + Ok(None) +} + pub async fn set_governor(governor: &Governor) -> Result<(), Error> { Command::new("cpupower") .arg("frequency-set") diff --git a/core/startos/src/version/mod.rs b/core/startos/src/version/mod.rs index a9d91cf73..2d888f05c 100644 --- a/core/startos/src/version/mod.rs +++ b/core/startos/src/version/mod.rs @@ -8,7 +8,7 @@ use sqlx::PgPool; use crate::prelude::*; use crate::Error; -mod v0_3_5; +mod v0_3_5_1; mod v0_4_0; pub type Current = v0_4_0::Version; @@ -16,8 +16,8 @@ pub type Current = v0_4_0::Version; #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[serde(untagged)] enum Version { - LT0_3_5(LTWrapper), - V0_3_5(Wrapper), + LT0_3_5_1(LTWrapper), + V0_3_5_1(Wrapper), V0_4_0(Wrapper), Other(emver::Version), } @@ -34,8 +34,8 @@ impl Version { #[cfg(test)] fn as_sem_ver(&self) -> emver::Version { match self { - Version::LT0_3_5(LTWrapper(_, x)) => x.clone(), - Version::V0_3_5(Wrapper(x)) => x.semver(), + Version::LT0_3_5_1(LTWrapper(_, x)) => x.clone(), + Version::V0_3_5_1(Wrapper(x)) => x.semver(), Version::V0_4_0(Wrapper(x)) => x.semver(), Version::Other(x) => x.clone(), } @@ -182,13 +182,13 @@ pub async fn init(db: &PatchDb, secrets: &PgPool) -> Result<(), Error> { let version = Version::from_util_version(db.peek().await.as_server_info().as_version().de()?); match version { - Version::LT0_3_5(_) => { + Version::LT0_3_5_1(_) => { return Err(Error::new( - eyre!("Cannot migrate from pre-0.3.5. Please update to v0.3.5 first."), + eyre!("Cannot migrate from pre-0.3.5.1. Please update to v0.3.5.1 first."), crate::ErrorKind::MigrationFailed, )); } - Version::V0_3_5(v) => v.0.migrate_to(&Current::new(), db, secrets).await?, + Version::V0_3_5_1(v) => v.0.migrate_to(&Current::new(), db, secrets).await?, Version::V0_4_0(v) => v.0.migrate_to(&Current::new(), db, secrets).await?, Version::Other(_) => { return Err(Error::new( @@ -222,15 +222,15 @@ mod tests { fn versions() -> impl Strategy { prop_oneof![ - em_version().prop_map(|v| if v < v0_3_5::Version::new().semver() { - Version::LT0_3_5(LTWrapper(v0_3_5::Version::new(), v)) + em_version().prop_map(|v| if v < v0_3_5_1::Version::new().semver() { + Version::LT0_3_5_1(LTWrapper(v0_3_5_1::Version::new(), v)) } else { - Version::LT0_3_5(LTWrapper( - v0_3_5::Version::new(), + Version::LT0_3_5_1(LTWrapper( + v0_3_5_1::Version::new(), emver::Version::new(0, 3, 0, 0), )) }), - Just(Version::V0_3_5(Wrapper(v0_3_5::Version::new()))), + Just(Version::V0_3_5_1(Wrapper(v0_3_5_1::Version::new()))), Just(Version::V0_4_0(Wrapper(v0_4_0::Version::new()))), em_version().prop_map(Version::Other), ] diff --git a/core/startos/src/version/v0_3_4.rs b/core/startos/src/version/v0_3_4.rs deleted file mode 100644 index e33dcb931..000000000 --- a/core/startos/src/version/v0_3_4.rs +++ /dev/null @@ -1,135 +0,0 @@ -use async_trait::async_trait; -use emver::VersionRange; -use itertools::Itertools; -use openssl::hash::MessageDigest; -use serde_json::json; -use ssh_key::public::Ed25519PublicKey; - -use super::*; -use crate::account::AccountInfo; -use crate::hostname::{sync_hostname, Hostname}; -use crate::prelude::*; - -const V0_3_4: emver::Version = emver::Version::new(0, 3, 4, 0); - -lazy_static::lazy_static! { - pub static ref V0_3_0_COMPAT: VersionRange = VersionRange::Conj( - Box::new(VersionRange::Anchor( - emver::GTE, - emver::Version::new(0, 3, 0, 0), - )), - Box::new(VersionRange::Anchor(emver::LTE, Current::new().semver())), - ); -} - -const COMMUNITY_URL: &str = "https://community-registry.start9.com/"; -const MAIN_REGISTRY: &str = "https://registry.start9.com/"; -const COMMUNITY_SERVICES: &[&str] = &[ - "ipfs", - "agora", - "lightning-jet", - "balanceofsatoshis", - "mastodon", - "lndg", - "robosats", - "thunderhub", - "syncthing", - "sphinx-relay", -]; - -#[derive(Clone, Debug)] -pub struct Version; - -#[async_trait] -impl VersionT for Version { - type Previous = Self; - fn new() -> Self { - Version - } - fn semver(&self) -> emver::Version { - V0_3_4 - } - fn compat(&self) -> &'static VersionRange { - &*V0_3_0_COMPAT - } - async fn up(&self, db: PatchDb, secrets: &PgPool) -> Result<(), Error> { - let mut account = AccountInfo::load(secrets).await?; - let account = db - .mutate(|d| { - d.as_server_info_mut().as_pubkey_mut().ser( - &ssh_key::PublicKey::from(Ed25519PublicKey::from(&account.key.ssh_key())) - .to_openssh()?, - )?; - d.as_server_info_mut().as_ca_fingerprint_mut().ser( - &account - .root_ca_cert - .digest(MessageDigest::sha256()) - .unwrap() - .iter() - .map(|x| format!("{x:X}")) - .join(":"), - )?; - let server_info = d.as_server_info(); - account.hostname = server_info.as_hostname().de().map(Hostname)?; - account.server_id = server_info.as_id().de()?; - - Ok(account) - }) - .await?; - account.save(secrets).await?; - sync_hostname(&account.hostname).await?; - - let parsed_url = Some(COMMUNITY_URL.parse().unwrap()); - db.mutate(|d| { - let mut ui = d.as_ui().de()?; - use imbl_value::json; - ui["marketplace"]["known-hosts"][COMMUNITY_URL] = json!({}); - ui["marketplace"]["known-hosts"][MAIN_REGISTRY] = json!({}); - for package_id in d.as_package_data().keys()? { - if !COMMUNITY_SERVICES.contains(&&*package_id.to_string()) { - continue; - } - d.as_package_data_mut() - .as_idx_mut(&package_id) - .or_not_found(&package_id)? - .as_installed_mut() - .or_not_found(&package_id)? - .as_marketplace_url_mut() - .ser(&parsed_url)?; - } - ui["theme"] = json!("Dark".to_string()); - ui["widgets"] = json!([]); - - d.as_ui_mut().ser(&ui) - }) - .await - } - async fn down(&self, db: PatchDb, _secrets: &PgPool) -> Result<(), Error> { - db.mutate(|d| { - let mut ui = d.as_ui().de()?; - let parsed_url = Some(MAIN_REGISTRY.parse().unwrap()); - for package_id in d.as_package_data().keys()? { - if !COMMUNITY_SERVICES.contains(&&*package_id.to_string()) { - continue; - } - d.as_package_data_mut() - .as_idx_mut(&package_id) - .or_not_found(&package_id)? - .as_installed_mut() - .or_not_found(&package_id)? - .as_marketplace_url_mut() - .ser(&parsed_url)?; - } - - if let imbl_value::Value::Object(ref mut obj) = ui { - obj.remove("theme"); - obj.remove("widgets"); - } - - ui["marketplace"]["known-hosts"][COMMUNITY_URL].take(); - ui["marketplace"]["known-hosts"][MAIN_REGISTRY].take(); - d.as_ui_mut().ser(&ui) - }) - .await - } -} diff --git a/core/startos/src/version/v0_3_4_1.rs b/core/startos/src/version/v0_3_4_1.rs deleted file mode 100644 index 915a47235..000000000 --- a/core/startos/src/version/v0_3_4_1.rs +++ /dev/null @@ -1,31 +0,0 @@ -use async_trait::async_trait; -use emver::VersionRange; - -use super::v0_3_4::V0_3_0_COMPAT; -use super::*; -use crate::prelude::*; - -const V0_3_4_1: emver::Version = emver::Version::new(0, 3, 4, 1); - -#[derive(Clone, Debug)] -pub struct Version; - -#[async_trait] -impl VersionT for Version { - type Previous = v0_3_4::Version; - fn new() -> Self { - Version - } - fn semver(&self) -> emver::Version { - V0_3_4_1 - } - fn compat(&self) -> &'static VersionRange { - &*V0_3_0_COMPAT - } - async fn up(&self, _db: PatchDb, _secrets: &PgPool) -> Result<(), Error> { - Ok(()) - } - async fn down(&self, _db: PatchDb, _secrets: &PgPool) -> Result<(), Error> { - Ok(()) - } -} diff --git a/core/startos/src/version/v0_3_4_2.rs b/core/startos/src/version/v0_3_4_2.rs deleted file mode 100644 index 5931b2879..000000000 --- a/core/startos/src/version/v0_3_4_2.rs +++ /dev/null @@ -1,31 +0,0 @@ -use async_trait::async_trait; -use emver::VersionRange; - -use super::v0_3_4::V0_3_0_COMPAT; -use super::*; -use crate::prelude::*; - -const V0_3_4_2: emver::Version = emver::Version::new(0, 3, 4, 2); - -#[derive(Clone, Debug)] -pub struct Version; - -#[async_trait] -impl VersionT for Version { - type Previous = v0_3_4_1::Version; - fn new() -> Self { - Version - } - fn semver(&self) -> emver::Version { - V0_3_4_2 - } - fn compat(&self) -> &'static VersionRange { - &*V0_3_0_COMPAT - } - async fn up(&self, _db: PatchDb, _secrets: &PgPool) -> Result<(), Error> { - Ok(()) - } - async fn down(&self, _db: PatchDb, _secrets: &PgPool) -> Result<(), Error> { - Ok(()) - } -} diff --git a/core/startos/src/version/v0_3_4_3.rs b/core/startos/src/version/v0_3_4_3.rs deleted file mode 100644 index d3199e913..000000000 --- a/core/startos/src/version/v0_3_4_3.rs +++ /dev/null @@ -1,31 +0,0 @@ -use async_trait::async_trait; -use emver::VersionRange; - -use super::v0_3_4::V0_3_0_COMPAT; -use super::*; -use crate::prelude::*; - -const V0_3_4_3: emver::Version = emver::Version::new(0, 3, 4, 3); - -#[derive(Clone, Debug)] -pub struct Version; - -#[async_trait] -impl VersionT for Version { - type Previous = v0_3_4_2::Version; - fn new() -> Self { - Version - } - fn semver(&self) -> emver::Version { - V0_3_4_3 - } - fn compat(&self) -> &'static VersionRange { - &V0_3_0_COMPAT - } - async fn up(&self, _db: PatchDb, _secrets: &PgPool) -> Result<(), Error> { - Ok(()) - } - async fn down(&self, _db: PatchDb, _secrets: &PgPool) -> Result<(), Error> { - Ok(()) - } -} diff --git a/core/startos/src/version/v0_3_4_4.rs b/core/startos/src/version/v0_3_4_4.rs deleted file mode 100644 index b6345ca4c..000000000 --- a/core/startos/src/version/v0_3_4_4.rs +++ /dev/null @@ -1,43 +0,0 @@ -use async_trait::async_trait; -use emver::VersionRange; -use models::ResultExt; -use sqlx::PgPool; - -use super::v0_3_4::V0_3_0_COMPAT; -use super::{v0_3_4_3, VersionT}; -use crate::prelude::*; - -const V0_3_4_4: emver::Version = emver::Version::new(0, 3, 4, 4); - -#[derive(Clone, Debug)] -pub struct Version; - -#[async_trait] -impl VersionT for Version { - type Previous = v0_3_4_3::Version; - fn new() -> Self { - Version - } - fn semver(&self) -> emver::Version { - V0_3_4_4 - } - fn compat(&self) -> &'static VersionRange { - &V0_3_0_COMPAT - } - async fn up(&self, db: PatchDb, _secrets: &PgPool) -> Result<(), Error> { - db.mutate(|v| { - let tor_address_lens = v.as_server_info_mut().as_tor_address_mut(); - let mut tor_addr = tor_address_lens.de()?; - tor_addr - .set_scheme("https") - .map_err(|_| eyre!("unable to update url scheme to https")) - .with_kind(crate::ErrorKind::ParseUrl)?; - tor_address_lens.ser(&tor_addr) - }) - .await?; - Ok(()) - } - async fn down(&self, _db: PatchDb, _secrets: &PgPool) -> Result<(), Error> { - Ok(()) - } -} diff --git a/core/startos/src/version/v0_3_5.rs b/core/startos/src/version/v0_3_5_1.rs similarity index 68% rename from core/startos/src/version/v0_3_5.rs rename to core/startos/src/version/v0_3_5_1.rs index 279897743..c9ce203c3 100644 --- a/core/startos/src/version/v0_3_5.rs +++ b/core/startos/src/version/v0_3_5_1.rs @@ -1,11 +1,11 @@ use async_trait::async_trait; use emver::VersionRange; -use lazy_static::lazy_static; +use sqlx::PgPool; -use super::*; +use super::v0_3_4::V0_3_0_COMPAT; +use super::VersionT; use crate::prelude::*; -const V0_3_5: emver::Version = emver::Version::new(0, 3, 5, 0); lazy_static! { static ref V0_3_0_COMPAT: VersionRange = VersionRange::Conj( Box::new(VersionRange::Anchor( @@ -15,6 +15,7 @@ lazy_static! { Box::new(VersionRange::Anchor(emver::LTE, Current::new().semver())), ); } +const V0_3_5_1: emver::Version = emver::Version::new(0, 3, 5, 1); #[derive(Clone, Debug)] pub struct Version; @@ -26,15 +27,15 @@ impl VersionT for Version { Version } fn semver(&self) -> emver::Version { - V0_3_5 + V0_3_5_1 } fn compat(&self) -> &'static VersionRange { &V0_3_0_COMPAT } - async fn up(&self, _db: &PatchDb, _secrets: &PgPool) -> Result<(), Error> { + async fn up(&self, _db: PatchDb, _secrets: &PgPool) -> Result<(), Error> { Ok(()) } - async fn down(&self, _db: &PatchDb, _secrets: &PgPool) -> Result<(), Error> { + async fn down(&self, _db: PatchDb, _secrets: &PgPool) -> Result<(), Error> { Ok(()) } } diff --git a/image-recipe/build.sh b/image-recipe/build.sh index bfc7921d9..633944642 100755 --- a/image-recipe/build.sh +++ b/image-recipe/build.sh @@ -158,8 +158,8 @@ echo "deb [arch=${IB_TARGET_ARCH} signed-by=/etc/apt/trusted.gpg.d/tor.key.gpg] curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o config/archives/docker.key echo "deb [arch=${IB_TARGET_ARCH} signed-by=/etc/apt/trusted.gpg.d/docker.key.gpg] https://download.docker.com/linux/debian ${IB_SUITE} stable" > config/archives/docker.list -curl -fsSL https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/Debian_Testing/Release.key | gpg --dearmor -o config/archives/podman.key -echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/podman.key.gpg] https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/Debian_Testing/ /" > config/archives/podman.list +curl -fsSL https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/Debian_Testing/Release.key | gpg --dearmor -o config/archives/podman.key +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/podman.key.gpg] https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/Debian_Testing/ /" > config/archives/podman.list # Dependencies diff --git a/system-images/compat/Cargo.lock b/system-images/compat/Cargo.lock index a431dbeb0..a80fb22a5 100644 --- a/system-images/compat/Cargo.lock +++ b/system-images/compat/Cargo.lock @@ -4418,7 +4418,7 @@ dependencies = [ [[package]] name = "start-os" -version = "0.3.5" +version = "0.3.5-rev.1" dependencies = [ "aes", "async-compression", diff --git a/web/package-lock.json b/web/package-lock.json index 52c2e39cb..900039e95 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "startos-ui", - "version": "0.3.5", + "version": "0.3.5.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "startos-ui", - "version": "0.3.5", + "version": "0.3.5.1", "dependencies": { "@angular/animations": "^14.1.0", "@angular/common": "^14.1.0", diff --git a/web/package.json b/web/package.json index 70e8161bc..ceaf4a594 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "startos-ui", - "version": "0.3.5", + "version": "0.3.5.1", "author": "Start9 Labs, Inc", "homepage": "https://start9.com/", "scripts": { diff --git a/web/projects/ui/src/app/apps/ui/pages/system/experimental-features/experimental-features.page.html b/web/projects/ui/src/app/apps/ui/pages/system/experimental-features/experimental-features.page.html index 69f82ff43..0ca8c7d8e 100644 --- a/web/projects/ui/src/app/apps/ui/pages/system/experimental-features/experimental-features.page.html +++ b/web/projects/ui/src/app/apps/ui/pages/system/experimental-features/experimental-features.page.html @@ -27,8 +27,8 @@

{{ server.zram ? 'Disable' : 'Enable' }} zram

- Enabling zram may improve server performance, especially on low RAM - devices + Zram creates compressed swap in memory, resulting in faster I/O for + low RAM devices

diff --git a/web/projects/ui/src/app/apps/ui/pages/system/experimental-features/experimental-features.page.ts b/web/projects/ui/src/app/apps/ui/pages/system/experimental-features/experimental-features.page.ts index ed57066ab..bf445250a 100644 --- a/web/projects/ui/src/app/apps/ui/pages/system/experimental-features/experimental-features.page.ts +++ b/web/projects/ui/src/app/apps/ui/pages/system/experimental-features/experimental-features.page.ts @@ -65,10 +65,10 @@ export class ExperimentalFeaturesPage { async presentAlertZram(enabled: boolean) { const alert = await this.alertCtrl.create({ - header: enabled ? 'Confirm' : 'Warning', + header: 'Confirm', message: enabled - ? 'Are you sure you want to disable zram?' - : 'zram on StartOS is experimental. It may increase performance of you server, especially if it is a low RAM device.', + ? 'Are you sure you want to disable zram? It provides significant performance benefits on low RAM devices.' + : 'Enable zram? It will only make a difference on lower RAM devices.', buttons: [ { text: 'Cancel', @@ -82,7 +82,6 @@ export class ExperimentalFeaturesPage { cssClass: 'enter-click', }, ], - cssClass: enabled ? '' : 'alert-warning-message', }) await alert.present() } @@ -122,7 +121,7 @@ export class ExperimentalFeaturesPage { private async toggleZram(enabled: boolean) { const loader = await this.loadingCtrl.create({ - message: enabled ? 'Disabling zram...' : 'Enabling zram', + message: enabled ? 'Disabling zram...' : 'Enabling zram...', }) await loader.present() diff --git a/web/projects/ui/src/app/modals/os-welcome/os-welcome.page.html b/web/projects/ui/src/app/modals/os-welcome/os-welcome.page.html index ed05ccb45..23bc7e1fd 100644 --- a/web/projects/ui/src/app/modals/os-welcome/os-welcome.page.html +++ b/web/projects/ui/src/app/modals/os-welcome/os-welcome.page.html @@ -12,6 +12,26 @@

This Release

+

0.3.5.1

+

+ View the complete + + release notes + + for more details. +

+
Highlights
+
    +
  • Revert perpetual performance mode for quieter fan
  • +
  • Minor bug fixes
  • +
+ +

Previous 0.3.5.x Releases

+

0.3.5

View the complete diff --git a/web/projects/ui/src/app/services/api/api.fixures.ts b/web/projects/ui/src/app/services/api/api.fixures.ts index cd983a280..f148d85c3 100644 --- a/web/projects/ui/src/app/services/api/api.fixures.ts +++ b/web/projects/ui/src/app/services/api/api.fixures.ts @@ -35,10 +35,10 @@ export module Mock { 'shutting-down': false, } export const MarketplaceEos: RR.GetMarketplaceEosRes = { - version: '0.3.5', + version: '0.3.5.1', headline: 'Our biggest release ever.', 'release-notes': { - '0.3.5': 'Some **Markdown** release _notes_ for 0.3.5', + '0.3.5.1': 'Some **Markdown** release _notes_ for 0.3.5.1', '0.3.4.4': 'Some **Markdown** release _notes_ for 0.3.4.4', '0.3.4.3': 'Some **Markdown** release _notes_ for 0.3.4.3', '0.3.4.2': 'Some **Markdown** release _notes_ for 0.3.4.2', diff --git a/web/projects/ui/src/app/services/api/mock-patch.ts b/web/projects/ui/src/app/services/api/mock-patch.ts index 5ceecad33..2c4693148 100644 --- a/web/projects/ui/src/app/services/api/mock-patch.ts +++ b/web/projects/ui/src/app/services/api/mock-patch.ts @@ -35,7 +35,7 @@ export const mockPatchData: DataModel = { }, 'server-info': { id: 'abcdefgh', - version: '0.3.5', + version: '0.3.5.1', country: 'us', 'last-backup': new Date(new Date().valueOf() - 604800001).toISOString(), 'lan-address': 'https://adjective-noun.local', diff --git a/web/projects/ui/src/manifest.webmanifest b/web/projects/ui/src/manifest.webmanifest index a199ac1dd..fee3469fc 100644 --- a/web/projects/ui/src/manifest.webmanifest +++ b/web/projects/ui/src/manifest.webmanifest @@ -5,8 +5,8 @@ "background_color": "#1e1e1e", "display": "standalone", "scope": ".", - "start_url": "/?version=035", - "id": "/?version=035", + "start_url": "/?version=0351", + "id": "/?version=0351", "icons": [ { "src": "assets/img/icon.png",