mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
Feature/install wizard disk info (#1923)
* update disk res for install wizard (#1914) * change types to match setup api Co-authored-by: Matt Hill <MattDHill@users.noreply.github.com>
This commit is contained in:
@@ -8,7 +8,6 @@ use helpers::NonDetachingJoinHandle;
|
|||||||
use patch_db::{DbHandle, LockReceipt, LockType};
|
use patch_db::{DbHandle, LockReceipt, LockType};
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
|
|
||||||
use crate::config::util::MergeWith;
|
|
||||||
use crate::context::rpc::RpcContextConfig;
|
use crate::context::rpc::RpcContextConfig;
|
||||||
use crate::db::model::ServerStatus;
|
use crate::db::model::ServerStatus;
|
||||||
use crate::install::PKG_DOCKER_DIR;
|
use crate::install::PKG_DOCKER_DIR;
|
||||||
|
|||||||
@@ -12,9 +12,11 @@ use crate::disk::mount::filesystem::bind::Bind;
|
|||||||
use crate::disk::mount::filesystem::block_dev::BlockDev;
|
use crate::disk::mount::filesystem::block_dev::BlockDev;
|
||||||
use crate::disk::mount::filesystem::ReadWrite;
|
use crate::disk::mount::filesystem::ReadWrite;
|
||||||
use crate::disk::mount::guard::{MountGuard, TmpMountGuard};
|
use crate::disk::mount::guard::{MountGuard, TmpMountGuard};
|
||||||
|
use crate::disk::util::DiskInfo;
|
||||||
use crate::disk::OsPartitionInfo;
|
use crate::disk::OsPartitionInfo;
|
||||||
use crate::util::serde::IoFormat;
|
use crate::util::serde::IoFormat;
|
||||||
use crate::util::{display_none, Invoke};
|
use crate::util::{display_none, Invoke};
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
@@ -24,28 +26,19 @@ pub struct PostInstallConfig {
|
|||||||
wifi_interface: Option<String>,
|
wifi_interface: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command(subcommands(status, execute, reboot))]
|
#[command(subcommands(disk, execute, reboot))]
|
||||||
pub fn install() -> Result<(), Error> {
|
pub fn install() -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[command(subcommands(list))]
|
||||||
#[serde(rename_all = "kebab-case")]
|
pub fn disk() -> Result<(), Error> {
|
||||||
pub struct InstallTarget {
|
Ok(())
|
||||||
logicalname: PathBuf,
|
|
||||||
embassy_data: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command(display(display_none))]
|
#[command(display(display_none))]
|
||||||
pub async fn status() -> Result<Vec<InstallTarget>, Error> {
|
pub async fn list() -> Result<Vec<DiskInfo>, Error> {
|
||||||
let disks = crate::disk::util::list(&Default::default()).await?;
|
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 find_wifi_iface() -> Result<Option<String>, Error> {
|
pub async fn find_wifi_iface() -> Result<Option<String>, Error> {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { IonicModule } from '@ionic/angular'
|
|||||||
import { FormsModule } from '@angular/forms'
|
import { FormsModule } from '@angular/forms'
|
||||||
import { HomePage } from './home.page'
|
import { HomePage } from './home.page'
|
||||||
import { SwiperModule } from 'swiper/angular'
|
import { SwiperModule } from 'swiper/angular'
|
||||||
|
import { UnitConversionPipesModule } from '@start9labs/shared'
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
@@ -20,6 +21,7 @@ const routes: Routes = [
|
|||||||
IonicModule,
|
IonicModule,
|
||||||
RouterModule.forChild(routes),
|
RouterModule.forChild(routes),
|
||||||
SwiperModule,
|
SwiperModule,
|
||||||
|
UnitConversionPipesModule,
|
||||||
],
|
],
|
||||||
declarations: [HomePage],
|
declarations: [HomePage],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -31,50 +31,61 @@
|
|||||||
<ion-item
|
<ion-item
|
||||||
*ngFor="let disk of disks"
|
*ngFor="let disk of disks"
|
||||||
button
|
button
|
||||||
detail="true"
|
|
||||||
(click)="next(disk)"
|
(click)="next(disk)"
|
||||||
>
|
>
|
||||||
<ion-icon
|
<ion-icon
|
||||||
color="dark"
|
|
||||||
slot="start"
|
slot="start"
|
||||||
name="save-outline"
|
name="save-outline"
|
||||||
|
size="large"
|
||||||
|
color="dark"
|
||||||
></ion-icon>
|
></ion-icon>
|
||||||
<ion-label>{{ disk.logicalname }}</ion-label>
|
<ion-label class="ion-text-wrap">
|
||||||
|
<h1>
|
||||||
|
{{ disk.vendor || 'Unknown Vendor' }} - {{ disk.model ||
|
||||||
|
'Unknown Model' }}
|
||||||
|
</h1>
|
||||||
|
<h2>
|
||||||
|
{{ disk.logicalname }} - {{ disk.capacity | convertBytes
|
||||||
|
}}
|
||||||
|
</h2>
|
||||||
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template swiperSlide>
|
<ng-template swiperSlide>
|
||||||
<ion-item
|
<ion-item
|
||||||
*ngIf="selectedDisk?.['embassy-data']"
|
*ngIf="!!selectedDisk?.guid"
|
||||||
button
|
button
|
||||||
(click)="tryInstall(false)"
|
(click)="tryInstall(false)"
|
||||||
>
|
>
|
||||||
<ion-icon
|
<ion-icon
|
||||||
color="dark"
|
color="dark"
|
||||||
slot="start"
|
slot="start"
|
||||||
|
size="large"
|
||||||
name="medkit-outline"
|
name="medkit-outline"
|
||||||
></ion-icon>
|
></ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>
|
<h1>
|
||||||
<ion-text color="success">Re-Install embassyOS</ion-text>
|
<ion-text color="success">Re-Install embassyOS</ion-text>
|
||||||
</h2>
|
</h1>
|
||||||
<h4>Will preserve existing embassyOS data</h4>
|
<h2>Will preserve existing embassyOS data</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item button lines="none" (click)="tryInstall(true)">
|
<ion-item button lines="none" (click)="tryInstall(true)">
|
||||||
<ion-icon
|
<ion-icon
|
||||||
color="dark"
|
color="dark"
|
||||||
slot="start"
|
slot="start"
|
||||||
|
size="large"
|
||||||
name="download-outline"
|
name="download-outline"
|
||||||
></ion-icon>
|
></ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>
|
<h1>
|
||||||
<ion-text
|
<ion-text
|
||||||
[color]="selectedDisk?.['embassy-data'] ? 'danger' : 'success'"
|
[color]="!!selectedDisk?.guid ? 'danger' : 'success'"
|
||||||
>{{ selectedDisk?.['embassy-data'] ? 'Factory Reset' :
|
>{{ !!selectedDisk?.guid ? 'Factory Reset' : 'Install
|
||||||
'Install embassyOS' }}</ion-text
|
embassyOS' }}</ion-text
|
||||||
>
|
>
|
||||||
</h2>
|
</h1>
|
||||||
<h4>Will delete existing data on disk</h4>
|
<h2>Will delete existing data on disk</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { AlertController, IonicSlides, LoadingController } from '@ionic/angular'
|
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 SwiperCore, { Swiper } from 'swiper'
|
||||||
|
import { DiskInfo } from '@start9labs/shared'
|
||||||
|
|
||||||
SwiperCore.use([IonicSlides])
|
SwiperCore.use([IonicSlides])
|
||||||
|
|
||||||
@@ -12,8 +13,8 @@ SwiperCore.use([IonicSlides])
|
|||||||
})
|
})
|
||||||
export class HomePage {
|
export class HomePage {
|
||||||
swiper?: Swiper
|
swiper?: Swiper
|
||||||
disks: Disk[] = []
|
disks: DiskInfo[] = []
|
||||||
selectedDisk?: Disk
|
selectedDisk?: DiskInfo
|
||||||
error = ''
|
error = ''
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -36,7 +37,7 @@ export class HomePage {
|
|||||||
this.swiper = swiper
|
this.swiper = swiper
|
||||||
}
|
}
|
||||||
|
|
||||||
next(disk: Disk) {
|
next(disk: DiskInfo) {
|
||||||
this.selectedDisk = disk
|
this.selectedDisk = disk
|
||||||
this.swiper?.slideNext(500)
|
this.swiper?.slideNext(500)
|
||||||
}
|
}
|
||||||
@@ -48,13 +49,15 @@ export class HomePage {
|
|||||||
async tryInstall(overwrite: boolean) {
|
async tryInstall(overwrite: boolean) {
|
||||||
if (!this.selectedDisk) return
|
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)
|
return this.install(logicalname, overwrite)
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.presentAlertDanger(logicalname, embassyData)
|
await this.presentAlertDanger(logicalname, hasEmbassyData)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async install(logicalname: string, overwrite: boolean) {
|
private async install(logicalname: string, overwrite: boolean) {
|
||||||
@@ -73,10 +76,13 @@ export class HomePage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async presentAlertDanger(logicalname: string, embassyData: boolean) {
|
private async presentAlertDanger(
|
||||||
const message = embassyData
|
logicalname: string,
|
||||||
? 'This action will COMPLETELY erase your existing Embassy data'
|
hasEmbassyData: boolean,
|
||||||
: `This action will COMPLETELY erase the disk <b>${logicalname}</b> and install embassyOS!`
|
) {
|
||||||
|
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({
|
const alert = await this.alertCtrl.create({
|
||||||
header: 'Warning',
|
header: 'Warning',
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
|
import { DiskInfo } from '@start9labs/shared'
|
||||||
|
|
||||||
export abstract class ApiService {
|
export abstract class ApiService {
|
||||||
abstract getDisks(): Promise<GetDisksRes> // install.status
|
abstract getDisks(): Promise<GetDisksRes> // install.disk.list
|
||||||
abstract install(params: InstallReq): Promise<void> // install.execute
|
abstract install(params: InstallReq): Promise<void> // install.execute
|
||||||
abstract reboot(): Promise<void> // install.reboot
|
abstract reboot(): Promise<void> // install.reboot
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GetDisksRes = Disk[]
|
export type GetDisksRes = DiskInfo[]
|
||||||
export type Disk = {
|
|
||||||
logicalname: string
|
|
||||||
'embassy-data': boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export type InstallReq = {
|
export type InstallReq = {
|
||||||
logicalname: string
|
logicalname: string
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export class LiveApiService implements ApiService {
|
|||||||
|
|
||||||
async getDisks(): Promise<GetDisksRes> {
|
async getDisks(): Promise<GetDisksRes> {
|
||||||
return this.rpcRequest({
|
return this.rpcRequest({
|
||||||
method: 'install.status',
|
method: 'install.disk.list',
|
||||||
params: {},
|
params: {},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,48 @@ export class MockApiService implements ApiService {
|
|||||||
await pauseFor(500)
|
await pauseFor(500)
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
logicalname: 'abcdefgh',
|
logicalname: 'abcd',
|
||||||
'embassy-data': false,
|
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',
|
logicalname: 'dcba',
|
||||||
'embassy-data': true,
|
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,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,8 @@ import {
|
|||||||
LoadingController,
|
LoadingController,
|
||||||
ModalController,
|
ModalController,
|
||||||
} from '@ionic/angular'
|
} from '@ionic/angular'
|
||||||
import {
|
import { ApiService, CifsBackupTarget } from 'src/app/services/api/api.service'
|
||||||
ApiService,
|
import { EmbassyOSDiskInfo } from '@start9labs/shared'
|
||||||
CifsBackupTarget,
|
|
||||||
EmbassyOSRecoveryInfo,
|
|
||||||
} from 'src/app/services/api/api.service'
|
|
||||||
import { PasswordPage } from '../password/password.page'
|
import { PasswordPage } from '../password/password.page'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -61,7 +58,7 @@ export class CifsModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async presentModalPassword(
|
private async presentModalPassword(
|
||||||
embassyOS: EmbassyOSRecoveryInfo,
|
embassyOS: EmbassyOSDiskInfo,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const target: CifsBackupTarget = {
|
const target: CifsBackupTarget = {
|
||||||
...this.cifs,
|
...this.cifs,
|
||||||
|
|||||||
@@ -8,10 +8,9 @@ import {
|
|||||||
import {
|
import {
|
||||||
ApiService,
|
ApiService,
|
||||||
BackupRecoverySource,
|
BackupRecoverySource,
|
||||||
DiskInfo,
|
|
||||||
DiskRecoverySource,
|
DiskRecoverySource,
|
||||||
} from 'src/app/services/api/api.service'
|
} 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 { StateService } from 'src/app/services/state.service'
|
||||||
import { PasswordPage } from '../../modals/password/password.page'
|
import { PasswordPage } from '../../modals/password/password.page'
|
||||||
import { ActivatedRoute } from '@angular/router'
|
import { ActivatedRoute } from '@angular/router'
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
<h2 class="target-label">Physical Drive</h2>
|
<h2 class="target-label">Physical Drive</h2>
|
||||||
<div class="ion-text-left ion-padding-bottom">
|
<div class="ion-text-left ion-padding-bottom">
|
||||||
<p>
|
<p>
|
||||||
Restore your Emabssy from a physcial drive that is plugged
|
Restore your Embassy from a physical drive that is plugged
|
||||||
directly into your Embassy.
|
directly into your Embassy.
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { AlertController, NavController } from '@ionic/angular'
|
import { AlertController, NavController } from '@ionic/angular'
|
||||||
import { ApiService, DiskInfo } from 'src/app/services/api/api.service'
|
import { ApiService } 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 { StateService } from 'src/app/services/state.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as jose from 'node-jose'
|
import * as jose from 'node-jose'
|
||||||
|
import { DiskListResponse, EmbassyOSDiskInfo } from '@start9labs/shared'
|
||||||
export abstract class ApiService {
|
export abstract class ApiService {
|
||||||
pubkey?: jose.JWK.Key
|
pubkey?: jose.JWK.Key
|
||||||
|
|
||||||
@@ -6,7 +7,7 @@ export abstract class ApiService {
|
|||||||
abstract getPubKey(): Promise<void> // setup.get-pubkey
|
abstract getPubKey(): Promise<void> // setup.get-pubkey
|
||||||
abstract getDrives(): Promise<DiskListResponse> // setup.disk.list
|
abstract getDrives(): Promise<DiskListResponse> // setup.disk.list
|
||||||
abstract getRecoveryStatus(): Promise<RecoveryStatusRes> // setup.recovery.status
|
abstract getRecoveryStatus(): Promise<RecoveryStatusRes> // setup.recovery.status
|
||||||
abstract verifyCifs(cifs: CifsRecoverySource): Promise<EmbassyOSRecoveryInfo> // setup.cifs.verify
|
abstract verifyCifs(cifs: CifsRecoverySource): Promise<EmbassyOSDiskInfo> // setup.cifs.verify
|
||||||
abstract importDrive(importInfo: ImportDriveReq): Promise<SetupEmbassyRes> // setup.attach
|
abstract importDrive(importInfo: ImportDriveReq): Promise<SetupEmbassyRes> // setup.attach
|
||||||
abstract setupEmbassy(setupInfo: SetupEmbassyReq): Promise<SetupEmbassyRes> // setup.execute
|
abstract setupEmbassy(setupInfo: SetupEmbassyReq): Promise<SetupEmbassyRes> // setup.execute
|
||||||
abstract setupComplete(): Promise<SetupEmbassyRes> // setup.complete
|
abstract setupComplete(): Promise<SetupEmbassyRes> // setup.complete
|
||||||
@@ -48,15 +49,6 @@ export type SetupEmbassyRes = {
|
|||||||
'root-ca': string
|
'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 = {
|
export type DiskBackupTarget = {
|
||||||
vendor: string | null
|
vendor: string | null
|
||||||
model: string | null
|
model: string | null
|
||||||
@@ -64,7 +56,7 @@ export type DiskBackupTarget = {
|
|||||||
label: string | null
|
label: string | null
|
||||||
capacity: number
|
capacity: number
|
||||||
used: number | null
|
used: number | null
|
||||||
'embassy-os': EmbassyOSRecoveryInfo | null
|
'embassy-os': EmbassyOSDiskInfo | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CifsBackupTarget = {
|
export type CifsBackupTarget = {
|
||||||
@@ -72,7 +64,7 @@ export type CifsBackupTarget = {
|
|||||||
path: string
|
path: string
|
||||||
username: string
|
username: string
|
||||||
mountable: boolean
|
mountable: boolean
|
||||||
'embassy-os': EmbassyOSRecoveryInfo | null
|
'embassy-os': EmbassyOSDiskInfo | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DiskRecoverySource = {
|
export type DiskRecoverySource = {
|
||||||
@@ -99,25 +91,8 @@ export type CifsRecoverySource = {
|
|||||||
password: Encrypted | null
|
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 = {
|
export type RecoveryStatusRes = {
|
||||||
'bytes-transferred': number
|
'bytes-transferred': number
|
||||||
'total-bytes': number
|
'total-bytes': number
|
||||||
complete: boolean
|
complete: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PartitionInfo = {
|
|
||||||
logicalname: string
|
|
||||||
label: string | null
|
|
||||||
capacity: number
|
|
||||||
used: number | null
|
|
||||||
'embassy-os': EmbassyOSRecoveryInfo | null
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import {
|
import {
|
||||||
|
DiskListResponse,
|
||||||
|
EmbassyOSDiskInfo,
|
||||||
encodeBase64,
|
encodeBase64,
|
||||||
HttpService,
|
HttpService,
|
||||||
isRpcError,
|
isRpcError,
|
||||||
@@ -9,10 +11,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
ApiService,
|
ApiService,
|
||||||
CifsRecoverySource,
|
CifsRecoverySource,
|
||||||
DiskListResponse,
|
|
||||||
DiskMigrateSource,
|
|
||||||
DiskRecoverySource,
|
DiskRecoverySource,
|
||||||
EmbassyOSRecoveryInfo,
|
|
||||||
GetStatusRes,
|
GetStatusRes,
|
||||||
ImportDriveReq,
|
ImportDriveReq,
|
||||||
RecoveryStatusRes,
|
RecoveryStatusRes,
|
||||||
@@ -68,7 +67,7 @@ export class LiveApiService extends ApiService {
|
|||||||
|
|
||||||
async verifyCifs(source: CifsRecoverySource) {
|
async verifyCifs(source: CifsRecoverySource) {
|
||||||
source.path = source.path.replace('/\\/g', '/')
|
source.path = source.path.replace('/\\/g', '/')
|
||||||
return this.rpcRequest<EmbassyOSRecoveryInfo>({
|
return this.rpcRequest<EmbassyOSDiskInfo>({
|
||||||
method: 'setup.cifs.verify',
|
method: 'setup.cifs.verify',
|
||||||
params: source,
|
params: source,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -14,3 +14,29 @@ export interface Log {
|
|||||||
timestamp: string
|
timestamp: string
|
||||||
message: 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
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
DependencyError,
|
DependencyError,
|
||||||
Manifest,
|
Manifest,
|
||||||
} from 'src/app/services/patch-db/data-model'
|
} from 'src/app/services/patch-db/data-model'
|
||||||
import { LogsRes, ServerLogsReq } from '@start9labs/shared'
|
import { EmbassyOSDiskInfo, LogsRes, ServerLogsReq } from '@start9labs/shared'
|
||||||
|
|
||||||
export module RR {
|
export module RR {
|
||||||
// DB
|
// DB
|
||||||
@@ -332,13 +332,6 @@ export type PlatformType =
|
|||||||
|
|
||||||
export type BackupTarget = DiskBackupTarget | CifsBackupTarget
|
export type BackupTarget = DiskBackupTarget | CifsBackupTarget
|
||||||
|
|
||||||
export interface EmbassyOSRecoveryInfo {
|
|
||||||
version: string
|
|
||||||
full: boolean
|
|
||||||
'password-hash': string | null
|
|
||||||
'wrapped-key': string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DiskBackupTarget {
|
export interface DiskBackupTarget {
|
||||||
type: 'disk'
|
type: 'disk'
|
||||||
vendor: string | null
|
vendor: string | null
|
||||||
@@ -347,7 +340,7 @@ export interface DiskBackupTarget {
|
|||||||
label: string | null
|
label: string | null
|
||||||
capacity: number
|
capacity: number
|
||||||
used: number | null
|
used: number | null
|
||||||
'embassy-os': EmbassyOSRecoveryInfo | null
|
'embassy-os': EmbassyOSDiskInfo | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CifsBackupTarget {
|
export interface CifsBackupTarget {
|
||||||
@@ -356,7 +349,7 @@ export interface CifsBackupTarget {
|
|||||||
path: string
|
path: string
|
||||||
username: string
|
username: string
|
||||||
mountable: boolean
|
mountable: boolean
|
||||||
'embassy-os': EmbassyOSRecoveryInfo | null
|
'embassy-os': EmbassyOSDiskInfo | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RecoverySource = DiskRecoverySource | CifsRecoverySource
|
export type RecoverySource = DiskRecoverySource | CifsRecoverySource
|
||||||
@@ -374,28 +367,6 @@ export interface CifsRecoverySource {
|
|||||||
password: string
|
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 {
|
export interface BackupInfo {
|
||||||
version: string
|
version: string
|
||||||
timestamp: string
|
timestamp: string
|
||||||
|
|||||||
Reference in New Issue
Block a user