diff --git a/Cargo.lock b/Cargo.lock index 656a0560f..c6cede3b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9405,6 +9405,7 @@ dependencies = [ "rustfs-config", "rustfs-ecstore", "rustfs-madmin", + "rustfs-storage-api", "rustfs-utils", "serde", "serde_json", @@ -9951,6 +9952,7 @@ dependencies = [ "rustfs-data-usage", "rustfs-ecstore", "rustfs-filemeta", + "rustfs-storage-api", "rustfs-utils", "s3s", "serde", diff --git a/crates/ecstore/src/rebalance.rs b/crates/ecstore/src/rebalance.rs index 7463fa0be..9f7d32068 100644 --- a/crates/ecstore/src/rebalance.rs +++ b/crates/ecstore/src/rebalance.rs @@ -28,6 +28,7 @@ use crate::store_api::{GetObjectReader, HTTPRangeSpec, ObjectIO, ObjectInfo, Obj use http::HeaderMap; use rand::RngExt as _; use rustfs_filemeta::{FileInfo, MetaCacheEntries, MetaCacheEntry, MetadataResolutionParams}; +use rustfs_storage_api::StorageAdminApi; use rustfs_utils::path::encode_dir_object; use serde::{Deserialize, Serialize}; use std::collections::HashSet; @@ -732,7 +733,7 @@ impl ECStore { #[tracing::instrument(skip(self))] pub async fn init_rebalance_meta(&self, bucktes: Vec) -> Result { info!("init_rebalance_meta: start rebalance"); - let si = self.storage_info().await; + let si = StorageAdminApi::storage_info(self).await; let mut disk_stats = vec![DiskStat::default(); self.pools.len()]; diff --git a/crates/heal/Cargo.toml b/crates/heal/Cargo.toml index 21b85c7cb..ecc798cae 100644 --- a/crates/heal/Cargo.toml +++ b/crates/heal/Cargo.toml @@ -29,6 +29,7 @@ categories = ["web-programming", "development-tools", "filesystem"] [dependencies] rustfs-config = { workspace = true } rustfs-ecstore = { workspace = true } +rustfs-storage-api = { workspace = true } rustfs-common = { workspace = true } rustfs-madmin = { workspace = true } rustfs-utils = { workspace = true } diff --git a/crates/heal/src/heal/storage.rs b/crates/heal/src/heal/storage.rs index 2c27f4364..4f2efe0e4 100644 --- a/crates/heal/src/heal/storage.rs +++ b/crates/heal/src/heal/storage.rs @@ -19,11 +19,10 @@ use rustfs_ecstore::{ disk::{DiskStore, endpoint::Endpoint}, error::StorageError, store::ECStore, - store_api::{ - BucketInfo, BucketOperations, HealOperations, ListOperations, ObjectIO, ObjectOperations, ObjectOptions, StorageAPI, - }, + store_api::{BucketInfo, BucketOperations, HealOperations, ListOperations, ObjectIO, ObjectOperations, ObjectOptions}, }; use rustfs_madmin::heal_commands::HealResultItem; +use rustfs_storage_api::{DiskSetSelector, StorageAdminApi}; use std::sync::Arc; use tracing::{debug, error, info, warn}; @@ -619,9 +618,7 @@ impl HealStorageAPI for ECStoreHealStorage { let (pool_idx, set_idx) = crate::heal::utils::parse_set_disk_id(set_disk_id)?; // Get the first available disk from the set - let disks = self - .ecstore - .get_disks(pool_idx, set_idx) + let disks = StorageAdminApi::disk_set_inventory(self.ecstore.as_ref(), DiskSetSelector::new(pool_idx, set_idx)) .await .map_err(|e| Error::TaskExecutionFailed { message: format!("Failed to get disks for pool {pool_idx} set {set_idx}: {e}"), diff --git a/crates/scanner/Cargo.toml b/crates/scanner/Cargo.toml index def18a36e..50f5fa01f 100644 --- a/crates/scanner/Cargo.toml +++ b/crates/scanner/Cargo.toml @@ -46,6 +46,7 @@ rmp-serde = { workspace = true } rustfs-filemeta = { workspace = true } tokio-util = { workspace = true } rustfs-ecstore = { workspace = true } +rustfs-storage-api = { workspace = true } http = { workspace = true } rand = { workspace = true } s3s = { workspace = true } diff --git a/crates/scanner/src/scanner_io.rs b/crates/scanner/src/scanner_io.rs index 1693d0fa8..3e554caed 100644 --- a/crates/scanner/src/scanner_io.rs +++ b/crates/scanner/src/scanner_io.rs @@ -44,6 +44,7 @@ use rustfs_ecstore::set_disk::SetDisks; use rustfs_ecstore::store_api::{BucketInfo, BucketOperations, BucketOptions, ObjectInfo}; use rustfs_ecstore::{StorageAPI, error::Result, store::ECStore}; use rustfs_filemeta::FileMeta; +use rustfs_storage_api::{DiskSetSelector, StorageAdminApi}; use rustfs_utils::path::path_join_buf; use s3s::dto::{BucketLifecycleConfiguration, ReplicationConfiguration}; use std::collections::{HashMap, HashSet}; @@ -1082,7 +1083,7 @@ impl ScannerIODisk for Disk { return Err(StorageError::other("Disk location not available".to_string())); }; - let disks_result = ecstore.get_disks(pool_idx, set_idx).await?; + let disks_result = StorageAdminApi::disk_set_inventory(ecstore.as_ref(), DiskSetSelector::new(pool_idx, set_idx)).await?; let Some(disk_idx) = disk_location.disk_idx else { error!("Disk index not available"); diff --git a/docs/architecture/migration-progress.md b/docs/architecture/migration-progress.md index c9834fb35..4d1a85250 100644 --- a/docs/architecture/migration-progress.md +++ b/docs/architecture/migration-progress.md @@ -5,17 +5,16 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block ## Current Context - Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660) -- Branch: `overtrue/arch-storage-admin-read-cleanup` -- Baseline: `origin/main` at `94c53af264b8d011b19b0b35eed5990a21592d70` +- Branch: `overtrue/arch-storage-admin-remaining-readers` +- Baseline: `origin/main` at `f325b9f71ce4807488829e6f558383242bbcb6a2` - PR type for this branch: `consumer-migration` - Runtime behavior changes: none. -- Rust code changes: route ECStore internal admin-read aggregation through - crate-internal `Sets`/`SetDisks` snapshot helpers and the inventory-facing - `StorageAdminApi` contract while preserving the old `StorageAPI` compatibility - surface. +- Rust code changes: route maintenance/background read-side storage inventory + consumers through the inventory-facing `StorageAdminApi` contract while + preserving the old `StorageAPI` compatibility surface. - CI/script changes: none. -- Docs changes: record API-007 internal admin-read cleanup context, verification - evidence, and expert review outcomes. +- Docs changes: record API-007 maintenance/background inventory-reader context, + verification evidence, and expert review outcomes. ## Phase 0 Tasks @@ -208,24 +207,38 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block - Completed fifth slice: `rustfs/rustfs#3335` migrated grouped observability, RPC health, server-info, realtime metrics, and notification read-side consumers. - - Current branch slice: add crate-internal admin snapshot helpers for - `Sets`/`SetDisks`, then migrate ECStore internal decommission space, - local-storage-info, backend-info, drive-count, and disk-inventory admin - handlers away from old `StorageAPI` method calls. - - Acceptance: ECStore internal admin-read aggregation no longer relies on old - `StorageAPI` method calls where crate-internal helpers or - `StorageAdminApi` already represent the same read-only contract. + - Completed sixth slice: `rustfs/rustfs#3336` migrated ECStore internal + decommission space, local-storage-info, backend-info, drive-count, and + disk-inventory admin handlers away from old `StorageAPI` method calls. + - Current branch slice: migrate maintenance/background read-side storage + inventory consumers in rebalance metadata initialization, heal resume disk + lookup, and scanner local disk scan lookup. + - Acceptance: these maintenance/background consumers no longer use old + `StorageAPI` calls for storage-info or disk-set inventory when the + inventory-facing `StorageAdminApi` contract already represents the same + read-only operation. - Must preserve: old `StorageAPI` trait shape, `StorageAPI::get_disks` - behavior, storage-info disk aggregation, local-only disk filtering, - decommission pool space calculation, storage-info deduplication, backend - info construction, object/rebalance selection paths, scanner/heal - consumers, object paths, replication/config persistence, and storage hot - paths. - - Risk defense: keep the old trait implementation as a delegating - compatibility surface, avoid implementing the full admin contract for - partial internal types, and do not migrate object APIs, scanner, heal, - replication, config persistence, or storage implementation hot paths in - this PR. + behavior, rebalance metadata serialization/save/load, heal resume disk + selection, scanner local disk selection, object/rebalance object selection + paths, scanner data-cache persistence, heal object repair, object paths, + replication/config/tier persistence, and storage hot paths. + - Risk defense: change only trait call entry points to existing ECStore + `StorageAdminApi` handlers; do not migrate object APIs, config or + replication persistence, scanner cache writes, heal object repair, or + storage implementation hot paths in this PR. + - Verification: + - `cargo fmt --all && cargo fmt --all --check`. + - `cargo check -p rustfs-ecstore -p rustfs-heal -p rustfs-scanner`. + - `cargo test -p rustfs-ecstore rebalance --lib`. + - `cargo test -p rustfs-heal storage --lib`. + - `cargo test -p rustfs-scanner scanner_io --lib`. + - `./scripts/check_architecture_migration_rules.sh`. + - `./scripts/check_layer_dependencies.sh`. + - `./scripts/check_metrics_migration_refs.sh`. + - `./scripts/check_unsafe_code_allowances.sh`. + - `git diff --check`. + - Pre-push review: pending required quality/architecture, + migration-preservation, and testing/verification review. ## Phase 8 Background Controller Tasks @@ -269,19 +282,18 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block | Expert | Status | Notes | |---|---|---| -| Quality/architecture | pass | Confirmed the diff stays limited to ECStore internal admin-read cleanup plus migration notes; helper visibility and naming are scoped, and the Handoff Notes correctly exclude object/hot-path `get_disks` consumers. | -| Migration preservation | pass | Confirmed old `StorageAPI` shape remains, `Sets`/`SetDisks` helpers preserve previous aggregation/filtering/get-disks logic, and decommission/local-info/admin inventory call sites only change entry point. | -| Testing/verification | pass | Confirmed focused ECStore checks, migration guards, diff hygiene, and added-line Rust quality scan are sufficient for this equivalent internal call-path cleanup while skipping full pre-commit under the current instruction. | +| Quality/architecture | pass | Confirmed the diff is limited to maintenance/background inventory-reader entry-point migration plus accurate progress notes; dependency direction, naming, and scope are clean. | +| Migration preservation | pass | Confirmed old `StorageAPI` shape remains, ECStore old/new trait paths still delegate to the same storage-info and disk-inventory handlers, and rebalance/heal/scanner call sites only change the read-side entry point. | +| Testing/verification | pass | Confirmed the focused ECStore/heal/scanner checks, migration guards, diff hygiene, and added-line Rust quality scan are sufficient for this equivalent read-side call-path migration while skipping full pre-commit under the current instruction. | ## Verification Notes Passed: -- `cargo fmt --all`. -- `cargo fmt --all --check`. -- `cargo check -p rustfs-ecstore`. -- `cargo test -p rustfs-ecstore store::rebalance --lib`; 19 passed. -- `cargo test -p rustfs-ecstore pools --lib`; 141 passed. -- `cargo test -p rustfs-ecstore set_disk --lib`; 86 passed. +- `cargo fmt --all && cargo fmt --all --check`. +- `cargo check -p rustfs-ecstore -p rustfs-heal -p rustfs-scanner`. +- `cargo test -p rustfs-ecstore rebalance --lib`; 198 passed. +- `cargo test -p rustfs-heal storage --lib`; 3 passed. +- `cargo test -p rustfs-scanner scanner_io --lib`; 18 passed. - `./scripts/check_architecture_migration_rules.sh`. - `./scripts/check_layer_dependencies.sh`. - `./scripts/check_metrics_migration_refs.sh`. @@ -297,21 +309,24 @@ Notes: - The broad changed-file quality scan reports pre-existing test unwrap/expect plus pre-existing casts and relaxed atomics in touched ECStore files; the added-line scan found no new risky code patterns. -- Old `StorageAPI` trait shape and implementations remain in place; `Sets` and - `SetDisks` delegate the admin-read subset to crate-internal helpers. -- Object/rebalance selection paths, scanner/heal consumers, object APIs, - replication/config persistence paths, and storage hot paths are unchanged. +- Old `StorageAPI` trait shape and implementations remain in place; ECStore old + and new trait paths delegate to the same storage-info and disk-inventory + handlers. +- Object/rebalance object selection paths, scanner cache persistence, heal + object repair, object APIs, replication/config/tier persistence paths, and + storage hot paths are unchanged. - No temporary compatibility shim was added. ## Handoff Notes -- Keep this API-007 slice as an ECStore-internal admin-read cleanup +- Keep this API-007 slice as a maintenance/background inventory-reader `consumer-migration` PR. -- Do not migrate object APIs, scanner, heal, replication, config persistence, or - storage hot-path consumers in this PR. +- The only scanner/heal scope in this PR is read-side disk lookup for scanner + local disk scan and heal resume; do not migrate scanner cache writes, heal + object repair, object APIs, replication, config/tier persistence, or storage + hot-path consumers in this PR. - Do not remove `StorageAPI::get_disks` or route object/hot-path consumers - around it in this PR; only the ECStore internal admin disk-inventory handler - is in scope. + around it in this PR. - Do not make the old `StorageAPI` trait inherit `StorageAdminApi` in this PR. - Do not add temporary compatibility code unless a matching `RUSTFS_COMPAT_TODO()` marker and cleanup-register entry are added.