From 4e47960440d36bb3539f152f883a3ecaff0d9b7b Mon Sep 17 00:00:00 2001 From: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com> Date: Wed, 9 Nov 2022 12:27:43 -0700 Subject: [PATCH] Feature/install wizard disk info (#1923) * update disk res for install wizard (#1914) * change types to match setup api Co-authored-by: Matt Hill --- backend/src/init.rs | 1 - backend/src/os_install.rs | 23 ++++------ .../src/app/pages/home/home.module.ts | 2 + .../src/app/pages/home/home.page.html | 37 ++++++++++------ .../src/app/pages/home/home.page.ts | 28 +++++++----- .../src/app/services/api/api.service.ts | 10 ++--- .../src/app/services/api/live-api.service.ts | 2 +- .../src/app/services/api/mock-api.service.ts | 44 +++++++++++++++++-- .../app/modals/cifs-modal/cifs-modal.page.ts | 9 ++-- .../src/app/pages/embassy/embassy.page.ts | 3 +- .../src/app/pages/recover/recover.page.html | 2 +- .../src/app/pages/transfer/transfer.page.ts | 4 +- .../src/app/services/api/api.service.ts | 33 ++------------ .../src/app/services/api/live-api.service.ts | 7 ++- frontend/projects/shared/src/types/api.ts | 26 +++++++++++ .../ui/src/app/services/api/api.types.ts | 35 ++------------- 16 files changed, 139 insertions(+), 127 deletions(-) diff --git a/backend/src/init.rs b/backend/src/init.rs index d9dde8f50..797415c51 100644 --- a/backend/src/init.rs +++ b/backend/src/init.rs @@ -8,7 +8,6 @@ use helpers::NonDetachingJoinHandle; use patch_db::{DbHandle, LockReceipt, LockType}; use tokio::process::Command; -use crate::config::util::MergeWith; use crate::context::rpc::RpcContextConfig; use crate::db::model::ServerStatus; use crate::install::PKG_DOCKER_DIR; diff --git a/backend/src/os_install.rs b/backend/src/os_install.rs index 29038c5f1..7f2f25735 100644 --- a/backend/src/os_install.rs +++ b/backend/src/os_install.rs @@ -12,9 +12,11 @@ use crate::disk::mount::filesystem::bind::Bind; use crate::disk::mount::filesystem::block_dev::BlockDev; use crate::disk::mount::filesystem::ReadWrite; use crate::disk::mount::guard::{MountGuard, TmpMountGuard}; +use crate::disk::util::DiskInfo; use crate::disk::OsPartitionInfo; use crate::util::serde::IoFormat; use crate::util::{display_none, Invoke}; +use crate::Error; #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] @@ -24,28 +26,19 @@ pub struct PostInstallConfig { wifi_interface: Option, } -#[command(subcommands(status, execute, reboot))] +#[command(subcommands(disk, execute, reboot))] pub fn install() -> Result<(), Error> { Ok(()) } -#[derive(Debug, Deserialize, Serialize)] -#[serde(rename_all = "kebab-case")] -pub struct InstallTarget { - logicalname: PathBuf, - embassy_data: bool, +#[command(subcommands(list))] +pub fn disk() -> Result<(), Error> { + Ok(()) } #[command(display(display_none))] -pub async fn status() -> Result, Error> { - let disks = crate::disk::util::list(&Default::default()).await?; - Ok(disks - .into_iter() - .map(|d| InstallTarget { - logicalname: d.logicalname, - embassy_data: d.guid.is_some() || d.partitions.into_iter().any(|p| p.guid.is_some()), - }) - .collect()) +pub async fn list() -> Result, Error> { + crate::disk::util::list(&Default::default()).await } pub async fn find_wifi_iface() -> Result, Error> { diff --git a/frontend/projects/install-wizard/src/app/pages/home/home.module.ts b/frontend/projects/install-wizard/src/app/pages/home/home.module.ts index 9608a1cf0..79afa2ac5 100644 --- a/frontend/projects/install-wizard/src/app/pages/home/home.module.ts +++ b/frontend/projects/install-wizard/src/app/pages/home/home.module.ts @@ -5,6 +5,7 @@ import { IonicModule } from '@ionic/angular' import { FormsModule } from '@angular/forms' import { HomePage } from './home.page' import { SwiperModule } from 'swiper/angular' +import { UnitConversionPipesModule } from '@start9labs/shared' const routes: Routes = [ { @@ -20,6 +21,7 @@ const routes: Routes = [ IonicModule, RouterModule.forChild(routes), SwiperModule, + UnitConversionPipesModule, ], declarations: [HomePage], }) diff --git a/frontend/projects/install-wizard/src/app/pages/home/home.page.html b/frontend/projects/install-wizard/src/app/pages/home/home.page.html index 8bb4a2f16..91e454d99 100644 --- a/frontend/projects/install-wizard/src/app/pages/home/home.page.html +++ b/frontend/projects/install-wizard/src/app/pages/home/home.page.html @@ -31,50 +31,61 @@ - {{ disk.logicalname }} + +

+ {{ disk.vendor || 'Unknown Vendor' }} - {{ disk.model || + 'Unknown Model' }} +

+

+ {{ disk.logicalname }} - {{ disk.capacity | convertBytes + }} +

+
-

+

Re-Install embassyOS -

-

Will preserve existing embassyOS data

+ +

Will preserve existing embassyOS data

-

+

{{ selectedDisk?.['embassy-data'] ? 'Factory Reset' : - 'Install embassyOS' }}{{ !!selectedDisk?.guid ? 'Factory Reset' : 'Install + embassyOS' }} -

-

Will delete existing data on disk

+ +

Will delete existing data on disk

diff --git a/frontend/projects/install-wizard/src/app/pages/home/home.page.ts b/frontend/projects/install-wizard/src/app/pages/home/home.page.ts index 199e452f7..4d77bbcc4 100644 --- a/frontend/projects/install-wizard/src/app/pages/home/home.page.ts +++ b/frontend/projects/install-wizard/src/app/pages/home/home.page.ts @@ -1,7 +1,8 @@ import { Component } from '@angular/core' import { AlertController, IonicSlides, LoadingController } from '@ionic/angular' -import { ApiService, Disk } from 'src/app/services/api/api.service' +import { ApiService } from 'src/app/services/api/api.service' import SwiperCore, { Swiper } from 'swiper' +import { DiskInfo } from '@start9labs/shared' SwiperCore.use([IonicSlides]) @@ -12,8 +13,8 @@ SwiperCore.use([IonicSlides]) }) export class HomePage { swiper?: Swiper - disks: Disk[] = [] - selectedDisk?: Disk + disks: DiskInfo[] = [] + selectedDisk?: DiskInfo error = '' constructor( @@ -36,7 +37,7 @@ export class HomePage { this.swiper = swiper } - next(disk: Disk) { + next(disk: DiskInfo) { this.selectedDisk = disk this.swiper?.slideNext(500) } @@ -48,13 +49,15 @@ export class HomePage { async tryInstall(overwrite: boolean) { if (!this.selectedDisk) return - const { logicalname, 'embassy-data': embassyData } = this.selectedDisk + const { logicalname, guid } = this.selectedDisk - if (embassyData && !overwrite) { + const hasEmbassyData = !!guid + + if (hasEmbassyData && !overwrite) { return this.install(logicalname, overwrite) } - await this.presentAlertDanger(logicalname, embassyData) + await this.presentAlertDanger(logicalname, hasEmbassyData) } private async install(logicalname: string, overwrite: boolean) { @@ -73,10 +76,13 @@ export class HomePage { } } - private async presentAlertDanger(logicalname: string, embassyData: boolean) { - const message = embassyData - ? 'This action will COMPLETELY erase your existing Embassy data' - : `This action will COMPLETELY erase the disk ${logicalname} and install embassyOS!` + private async presentAlertDanger( + logicalname: string, + hasEmbassyData: boolean, + ) { + const message = hasEmbassyData + ? 'This action COMPLETELY erases your existing Embassy data' + : `This action COMPLETELY erases the disk ${logicalname} and installs embassyOS` const alert = await this.alertCtrl.create({ header: 'Warning', diff --git a/frontend/projects/install-wizard/src/app/services/api/api.service.ts b/frontend/projects/install-wizard/src/app/services/api/api.service.ts index 704d583a1..2114ef2f4 100644 --- a/frontend/projects/install-wizard/src/app/services/api/api.service.ts +++ b/frontend/projects/install-wizard/src/app/services/api/api.service.ts @@ -1,14 +1,12 @@ +import { DiskInfo } from '@start9labs/shared' + export abstract class ApiService { - abstract getDisks(): Promise // install.status + abstract getDisks(): Promise // install.disk.list abstract install(params: InstallReq): Promise // install.execute abstract reboot(): Promise // install.reboot } -export type GetDisksRes = Disk[] -export type Disk = { - logicalname: string - 'embassy-data': boolean -} +export type GetDisksRes = DiskInfo[] export type InstallReq = { logicalname: string diff --git a/frontend/projects/install-wizard/src/app/services/api/live-api.service.ts b/frontend/projects/install-wizard/src/app/services/api/live-api.service.ts index 791699fad..dc9b92488 100644 --- a/frontend/projects/install-wizard/src/app/services/api/live-api.service.ts +++ b/frontend/projects/install-wizard/src/app/services/api/live-api.service.ts @@ -13,7 +13,7 @@ export class LiveApiService implements ApiService { async getDisks(): Promise { return this.rpcRequest({ - method: 'install.status', + method: 'install.disk.list', params: {}, }) } diff --git a/frontend/projects/install-wizard/src/app/services/api/mock-api.service.ts b/frontend/projects/install-wizard/src/app/services/api/mock-api.service.ts index 05d0e074f..9f035d2cd 100644 --- a/frontend/projects/install-wizard/src/app/services/api/mock-api.service.ts +++ b/frontend/projects/install-wizard/src/app/services/api/mock-api.service.ts @@ -8,12 +8,48 @@ export class MockApiService implements ApiService { await pauseFor(500) return [ { - logicalname: 'abcdefgh', - 'embassy-data': false, + logicalname: 'abcd', + vendor: 'Samsung', + model: 'T5', + partitions: [ + { + logicalname: 'pabcd', + label: null, + capacity: 73264762332, + used: null, + 'embassy-os': { + version: '0.2.17', + full: true, + 'password-hash': + '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', + 'wrapped-key': null, + }, + }, + ], + capacity: 123456789123, + guid: 'uuid-uuid-uuid-uuid', }, { - logicalname: '12345678', - 'embassy-data': true, + logicalname: 'dcba', + vendor: 'Crucial', + model: 'MX500', + partitions: [ + { + logicalname: 'pbcba', + label: null, + capacity: 73264762332, + used: null, + 'embassy-os': { + version: '0.3.1', + full: true, + 'password-hash': + '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', + 'wrapped-key': null, + }, + }, + ], + capacity: 123456789123, + guid: null, }, ] } diff --git a/frontend/projects/setup-wizard/src/app/modals/cifs-modal/cifs-modal.page.ts b/frontend/projects/setup-wizard/src/app/modals/cifs-modal/cifs-modal.page.ts index febc606a9..60b2d1a9a 100644 --- a/frontend/projects/setup-wizard/src/app/modals/cifs-modal/cifs-modal.page.ts +++ b/frontend/projects/setup-wizard/src/app/modals/cifs-modal/cifs-modal.page.ts @@ -4,11 +4,8 @@ import { LoadingController, ModalController, } from '@ionic/angular' -import { - ApiService, - CifsBackupTarget, - EmbassyOSRecoveryInfo, -} from 'src/app/services/api/api.service' +import { ApiService, CifsBackupTarget } from 'src/app/services/api/api.service' +import { EmbassyOSDiskInfo } from '@start9labs/shared' import { PasswordPage } from '../password/password.page' @Component({ @@ -61,7 +58,7 @@ export class CifsModal { } private async presentModalPassword( - embassyOS: EmbassyOSRecoveryInfo, + embassyOS: EmbassyOSDiskInfo, ): Promise { const target: CifsBackupTarget = { ...this.cifs, diff --git a/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.page.ts b/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.page.ts index 3cb6f4483..4dcc2f13d 100644 --- a/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.page.ts +++ b/frontend/projects/setup-wizard/src/app/pages/embassy/embassy.page.ts @@ -8,10 +8,9 @@ import { import { ApiService, BackupRecoverySource, - DiskInfo, DiskRecoverySource, } from 'src/app/services/api/api.service' -import { ErrorToastService } from '@start9labs/shared' +import { DiskInfo, ErrorToastService } from '@start9labs/shared' import { StateService } from 'src/app/services/state.service' import { PasswordPage } from '../../modals/password/password.page' import { ActivatedRoute } from '@angular/router' diff --git a/frontend/projects/setup-wizard/src/app/pages/recover/recover.page.html b/frontend/projects/setup-wizard/src/app/pages/recover/recover.page.html index 8334de7f9..10da48bb2 100644 --- a/frontend/projects/setup-wizard/src/app/pages/recover/recover.page.html +++ b/frontend/projects/setup-wizard/src/app/pages/recover/recover.page.html @@ -47,7 +47,7 @@

Physical Drive

- Restore your Emabssy from a physcial drive that is plugged + Restore your Embassy from a physical drive that is plugged directly into your Embassy.


diff --git a/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.page.ts b/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.page.ts index bf2670772..db87f86df 100644 --- a/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.page.ts +++ b/frontend/projects/setup-wizard/src/app/pages/transfer/transfer.page.ts @@ -1,7 +1,7 @@ import { Component } from '@angular/core' import { AlertController, NavController } from '@ionic/angular' -import { ApiService, DiskInfo } from 'src/app/services/api/api.service' -import { ErrorToastService } from '@start9labs/shared' +import { ApiService } from 'src/app/services/api/api.service' +import { DiskInfo, ErrorToastService } from '@start9labs/shared' import { StateService } from 'src/app/services/state.service' @Component({ diff --git a/frontend/projects/setup-wizard/src/app/services/api/api.service.ts b/frontend/projects/setup-wizard/src/app/services/api/api.service.ts index 161dc8bad..c827e5e10 100644 --- a/frontend/projects/setup-wizard/src/app/services/api/api.service.ts +++ b/frontend/projects/setup-wizard/src/app/services/api/api.service.ts @@ -1,4 +1,5 @@ import * as jose from 'node-jose' +import { DiskListResponse, EmbassyOSDiskInfo } from '@start9labs/shared' export abstract class ApiService { pubkey?: jose.JWK.Key @@ -6,7 +7,7 @@ export abstract class ApiService { abstract getPubKey(): Promise // setup.get-pubkey abstract getDrives(): Promise // setup.disk.list abstract getRecoveryStatus(): Promise // setup.recovery.status - abstract verifyCifs(cifs: CifsRecoverySource): Promise // setup.cifs.verify + abstract verifyCifs(cifs: CifsRecoverySource): Promise // setup.cifs.verify abstract importDrive(importInfo: ImportDriveReq): Promise // setup.attach abstract setupEmbassy(setupInfo: SetupEmbassyReq): Promise // setup.execute abstract setupComplete(): Promise // setup.complete @@ -48,15 +49,6 @@ export type SetupEmbassyRes = { 'root-ca': string } -export type EmbassyOSRecoveryInfo = { - version: string - full: boolean - 'password-hash': string | null - 'wrapped-key': string | null -} - -export type DiskListResponse = DiskInfo[] - export type DiskBackupTarget = { vendor: string | null model: string | null @@ -64,7 +56,7 @@ export type DiskBackupTarget = { label: string | null capacity: number used: number | null - 'embassy-os': EmbassyOSRecoveryInfo | null + 'embassy-os': EmbassyOSDiskInfo | null } export type CifsBackupTarget = { @@ -72,7 +64,7 @@ export type CifsBackupTarget = { path: string username: string mountable: boolean - 'embassy-os': EmbassyOSRecoveryInfo | null + 'embassy-os': EmbassyOSDiskInfo | null } export type DiskRecoverySource = { @@ -99,25 +91,8 @@ export type CifsRecoverySource = { password: Encrypted | null } -export type DiskInfo = { - logicalname: string - vendor: string | null - model: string | null - partitions: PartitionInfo[] - capacity: number - guid: string | null // cant back up if guid exists, but needed if migrating -} - export type RecoveryStatusRes = { 'bytes-transferred': number 'total-bytes': number complete: boolean } - -export type PartitionInfo = { - logicalname: string - label: string | null - capacity: number - used: number | null - 'embassy-os': EmbassyOSRecoveryInfo | null -} diff --git a/frontend/projects/setup-wizard/src/app/services/api/live-api.service.ts b/frontend/projects/setup-wizard/src/app/services/api/live-api.service.ts index 6ec6496ff..2b0be6613 100644 --- a/frontend/projects/setup-wizard/src/app/services/api/live-api.service.ts +++ b/frontend/projects/setup-wizard/src/app/services/api/live-api.service.ts @@ -1,5 +1,7 @@ import { Injectable } from '@angular/core' import { + DiskListResponse, + EmbassyOSDiskInfo, encodeBase64, HttpService, isRpcError, @@ -9,10 +11,7 @@ import { import { ApiService, CifsRecoverySource, - DiskListResponse, - DiskMigrateSource, DiskRecoverySource, - EmbassyOSRecoveryInfo, GetStatusRes, ImportDriveReq, RecoveryStatusRes, @@ -68,7 +67,7 @@ export class LiveApiService extends ApiService { async verifyCifs(source: CifsRecoverySource) { source.path = source.path.replace('/\\/g', '/') - return this.rpcRequest({ + return this.rpcRequest({ method: 'setup.cifs.verify', params: source, }) diff --git a/frontend/projects/shared/src/types/api.ts b/frontend/projects/shared/src/types/api.ts index 5c483d50e..21a869c4c 100644 --- a/frontend/projects/shared/src/types/api.ts +++ b/frontend/projects/shared/src/types/api.ts @@ -14,3 +14,29 @@ export interface Log { timestamp: string message: string } + +export type DiskListResponse = DiskInfo[] + +export interface DiskInfo { + logicalname: string + vendor: string | null + model: string | null + partitions: PartitionInfo[] + capacity: number + guid: string | null +} + +export interface PartitionInfo { + logicalname: string + label: string | null + capacity: number + used: number | null + 'embassy-os': EmbassyOSDiskInfo | null +} + +export type EmbassyOSDiskInfo = { + version: string + full: boolean + 'password-hash': string | null + 'wrapped-key': string | null +} diff --git a/frontend/projects/ui/src/app/services/api/api.types.ts b/frontend/projects/ui/src/app/services/api/api.types.ts index 8012350ff..a60e5d782 100644 --- a/frontend/projects/ui/src/app/services/api/api.types.ts +++ b/frontend/projects/ui/src/app/services/api/api.types.ts @@ -7,7 +7,7 @@ import { DependencyError, Manifest, } from 'src/app/services/patch-db/data-model' -import { LogsRes, ServerLogsReq } from '@start9labs/shared' +import { EmbassyOSDiskInfo, LogsRes, ServerLogsReq } from '@start9labs/shared' export module RR { // DB @@ -332,13 +332,6 @@ export type PlatformType = export type BackupTarget = DiskBackupTarget | CifsBackupTarget -export interface EmbassyOSRecoveryInfo { - version: string - full: boolean - 'password-hash': string | null - 'wrapped-key': string | null -} - export interface DiskBackupTarget { type: 'disk' vendor: string | null @@ -347,7 +340,7 @@ export interface DiskBackupTarget { label: string | null capacity: number used: number | null - 'embassy-os': EmbassyOSRecoveryInfo | null + 'embassy-os': EmbassyOSDiskInfo | null } export interface CifsBackupTarget { @@ -356,7 +349,7 @@ export interface CifsBackupTarget { path: string username: string mountable: boolean - 'embassy-os': EmbassyOSRecoveryInfo | null + 'embassy-os': EmbassyOSDiskInfo | null } export type RecoverySource = DiskRecoverySource | CifsRecoverySource @@ -374,28 +367,6 @@ export interface CifsRecoverySource { password: string } -export interface DiskInfo { - logicalname: string - vendor: string | null - model: string | null - partitions: PartitionInfo[] - capacity: number - guid: string | null -} - -export interface PartitionInfo { - logicalname: string - label: string | null - capacity: number - used: number | null - 'embassy-os': EmbassyOsDiskInfo | null -} - -export interface EmbassyOsDiskInfo { - version: string - full: boolean -} - export interface BackupInfo { version: string timestamp: string