diff --git a/ecstore/src/sets.rs b/ecstore/src/sets.rs index c5dc2c07c..384983441 100644 --- a/ecstore/src/sets.rs +++ b/ecstore/src/sets.rs @@ -22,9 +22,9 @@ use crate::{ }, set_disk::SetDisks, store_api::{ - BucketInfo, BucketOptions, CompletePart, DeleteBucketOptions, DeletedObject, GetObjectReader, HTTPRangeSpec, + BackendInfo, BucketInfo, BucketOptions, CompletePart, DeleteBucketOptions, DeletedObject, GetObjectReader, HTTPRangeSpec, ListMultipartsInfo, ListObjectsV2Info, MakeBucketOptions, MultipartUploadResult, ObjectIO, ObjectInfo, ObjectOptions, - ObjectToDelete, PartInfo, PutObjReader, StorageAPI, + ObjectToDelete, PartInfo, PutObjReader, StorageAPI, StorageInfo, }, utils::hash, }; @@ -47,6 +47,7 @@ pub struct Sets { pub partiy_count: usize, pub set_count: usize, pub set_drive_count: usize, + pub default_parity_count: usize, pub distribution_algo: DistributionAlgoVersion, ctx: CancellationToken, } @@ -152,6 +153,7 @@ impl Sets { partiy_count, set_count, set_drive_count, + default_parity_count: partiy_count, distribution_algo: fm.erasure.distribution_algo.clone(), ctx: CancellationToken::new(), }); @@ -286,6 +288,28 @@ impl ObjectIO for Sets { #[async_trait::async_trait] impl StorageAPI for Sets { + async fn backend_info(&self) -> BackendInfo { + unimplemented!() + } + async fn storage_info(&self) -> StorageInfo { + unimplemented!() + } + async fn local_storage_info(&self) -> StorageInfo { + let mut futures = Vec::with_capacity(self.disk_set.len()); + + for set in self.disk_set.iter() { + futures.push(set.local_storage_info()) + } + + let results = join_all(futures).await; + + let mut disks = Vec::new(); + + for res in results.into_iter() { + disks.extend_from_slice(&res.disks); + } + StorageInfo { backend: None, disks } + } async fn list_bucket(&self, _opts: &BucketOptions) -> Result> { unimplemented!() } diff --git a/ecstore/src/store.rs b/ecstore/src/store.rs index 98627c709..7e0e1773c 100644 --- a/ecstore/src/store.rs +++ b/ecstore/src/store.rs @@ -3,6 +3,7 @@ use crate::bucket::metadata; use crate::bucket::metadata_sys::{self, init_bucket_metadata_sys, set_bucket_metadata}; use crate::bucket::utils::{check_valid_bucket_name, check_valid_bucket_name_strict, is_meta_bucketname}; +use crate::config::GLOBAL_StorageClass; use crate::config::{self, storageclass, GLOBAL_ConfigSys}; use crate::disk::endpoint::EndpointType; use crate::disk::{DiskAPI, DiskInfo, DiskInfoOptions, MetaCacheEntry}; @@ -13,7 +14,7 @@ use crate::global::{ use crate::heal::heal_commands::{HealOpts, HealResultItem, HealScanMode}; use crate::heal::heal_ops::HealObjectFn; use crate::new_object_layer_fn; -use crate::store_api::{ListMultipartsInfo, ObjectIO}; +use crate::store_api::{BackendByte, BackendDisks, BackendInfo, ListMultipartsInfo, ObjectIO, StorageInfo}; use crate::store_err::{ is_err_bucket_exists, is_err_invalid_upload_id, is_err_object_not_found, is_err_version_not_found, StorageError, }; @@ -791,6 +792,74 @@ lazy_static! { #[async_trait::async_trait] impl StorageAPI for ECStore { + async fn backend_info(&self) -> BackendInfo { + let (standard_scparities, rrscparities) = { + if let Some(sc) = GLOBAL_StorageClass.get() { + let sc_parity = sc + .get_parity_for_sc(storageclass::CLASS_STANDARD) + .or(Some(self.pools[0].default_parity_count)); + + let rrs_sc_parity = sc.get_parity_for_sc(storageclass::RRS); + + (sc_parity, rrs_sc_parity) + } else { + (Some(self.pools[0].default_parity_count), None) + } + }; + + let mut standard_scdata = Vec::new(); + let mut rrscdata = Vec::new(); + let mut drives_per_set = Vec::new(); + let mut total_sets = Vec::new(); + + for (idx, set_count) in self.set_drive_counts().iter().enumerate() { + if let Some(sc_parity) = standard_scparities { + standard_scdata.push(set_count - sc_parity); + } + if let Some(rr_sc_parity) = rrscparities { + rrscdata.push(set_count - rr_sc_parity); + } + total_sets.push(self.pools[idx].set_count); + drives_per_set.push(*set_count); + } + + BackendInfo { + backend_type: BackendByte::Erasure, + online_disks: BackendDisks::new(), + offline_disks: BackendDisks::new(), + standard_scdata, + standard_scparities, + rrscdata, + rrscparities, + total_sets, + drives_per_set, + } + } + async fn storage_info(&self) -> StorageInfo { + unimplemented!() + } + async fn local_storage_info(&self) -> StorageInfo { + let mut futures = Vec::with_capacity(self.pools.len()); + + for pool in self.pools.iter() { + futures.push(pool.local_storage_info()) + } + + let results = join_all(futures).await; + + let mut disks = Vec::new(); + + for res in results.into_iter() { + disks.extend_from_slice(&res.disks); + } + + let backend = self.backend_info().await; + StorageInfo { + backend: Some(backend), + disks, + } + } + async fn list_bucket(&self, opts: &BucketOptions) -> Result> { // TODO: opts.cached diff --git a/ecstore/src/store_api.rs b/ecstore/src/store_api.rs index 21df384ed..9cc6517a5 100644 --- a/ecstore/src/store_api.rs +++ b/ecstore/src/store_api.rs @@ -778,6 +778,75 @@ pub struct DeletedObject { // pub replication_state: ReplicationState, } +#[derive(Debug, Default)] +pub enum BackendByte { + #[default] + Unknown, + FS, + Erasure, +} + +#[derive(Serialize, Deserialize, Debug, Default, Clone)] +pub struct StorageDisk { + pub endpoint: String, + pub root_disk: bool, + pub drive_path: String, + pub healing: bool, + pub scanning: bool, + pub state: String, + pub uuid: String, + pub major: u32, + pub minor: u32, + pub model: Option, + pub total_space: u64, + pub used_space: u64, + pub available_space: u64, + pub read_throughput: f64, + pub write_throughput: f64, + pub read_latency: f64, + pub write_latency: f64, + pub utilization: f64, + // pub metrics: Option, + // pub heal_info: Option, + pub used_inodes: u64, + pub free_inodes: u64, + pub local: bool, + pub pool_index: Option, + pub set_index: Option, + pub disk_index: Option, +} + +#[derive(Debug, Default)] +pub struct StorageInfo { + pub disks: Vec, + pub backend: Option, +} + +#[derive(Debug, Default)] +pub struct BackendDisks(HashMap); + +impl BackendDisks { + pub fn new() -> Self { + Self(HashMap::new()) + } + pub fn sum(&self) -> usize { + self.0.values().sum() + } +} + +#[derive(Debug, Default)] +pub struct BackendInfo { + pub backend_type: BackendByte, + pub online_disks: BackendDisks, + pub offline_disks: BackendDisks, + pub standard_scdata: Vec, + pub standard_scparities: Option, + pub rrscdata: Vec, + pub rrscparities: Option, + pub total_sets: Vec, + pub drives_per_set: Vec, +} + #[async_trait::async_trait] pub trait ObjectIO: Send + Sync + 'static { // GetObjectNInfo @@ -798,9 +867,10 @@ pub trait StorageAPI: ObjectIO { // NewNSLock // Shutdown // NSScanner - // BackendInfo - // StorageInfo - // LocalStorageInfo + + async fn backend_info(&self) -> BackendInfo; + async fn storage_info(&self) -> StorageInfo; + async fn local_storage_info(&self) -> StorageInfo; async fn make_bucket(&self, bucket: &str, opts: &MakeBucketOptions) -> Result<()>; async fn get_bucket_info(&self, bucket: &str, opts: &BucketOptions) -> Result;