diff --git a/io-engine/src/core/env.rs b/io-engine/src/core/env.rs index 31ca117c9..e214b2238 100644 --- a/io-engine/src/core/env.rs +++ b/io-engine/src/core/env.rs @@ -282,8 +282,8 @@ impl MayastorFeatures { snapshot_rebuild, } } - - pub fn get_features() -> Self { + /// Get all the supported and enabled features. + pub fn get() -> Self { MAYASTOR_FEATURES.get_or_init(Self::init_features).clone() } } @@ -513,7 +513,7 @@ async fn do_shutdown(arg: *mut c_void) { nexus::shutdown_nexuses().await; crate::rebuild::shutdown_snapshot_rebuilds().await; crate::lvs::Lvs::export_all().await; - if MayastorFeatures::get_features().lvm() { + if MayastorFeatures::get().lvm() { crate::lvm::VolumeGroup::export_all().await; } diff --git a/io-engine/src/core/mod.rs b/io-engine/src/core/mod.rs index 630b2a65b..d9af39313 100644 --- a/io-engine/src/core/mod.rs +++ b/io-engine/src/core/mod.rs @@ -531,7 +531,24 @@ pub struct MayastorFeatures { pub snapshot_rebuild: bool, } impl MayastorFeatures { + /// Check if LVM feature is enabled. pub fn lvm(&self) -> bool { self.logical_volume_manager } } + +/// Bugfix information to expose to the control-plane. +#[derive(Debug, Clone)] +pub(crate) struct MayastorBugFixes { + /// Nexus Rebuild rebuilds all the clusters allocated to the replica and + /// its ancestors. + pub nexus_rebuild_replica_ancestry: bool, +} +impl MayastorBugFixes { + /// Get all the bug fixes. + pub fn get() -> Self { + Self { + nexus_rebuild_replica_ancestry: true, + } + } +} diff --git a/io-engine/src/grpc/mod.rs b/io-engine/src/grpc/mod.rs index d0035c51a..b1c978646 100644 --- a/io-engine/src/grpc/mod.rs +++ b/io-engine/src/grpc/mod.rs @@ -346,7 +346,7 @@ pub fn get_request_timeout(req: &Request) -> Duration { } fn lvm_enabled() -> Result<(), Status> { - if !MayastorFeatures::get_features().lvm() { + if !MayastorFeatures::get().lvm() { return Err(Status::failed_precondition("lvm support not enabled")); } Ok(()) diff --git a/io-engine/src/grpc/v0/mayastor_grpc.rs b/io-engine/src/grpc/v0/mayastor_grpc.rs index 8ea540371..0d4601f84 100644 --- a/io-engine/src/grpc/v0/mayastor_grpc.rs +++ b/io-engine/src/grpc/v0/mayastor_grpc.rs @@ -1836,7 +1836,7 @@ impl mayastor_server::Mayastor for MayastorSvc { &self, _request: Request, ) -> GrpcResult { - let features = MayastorFeatures::get_features().into(); + let features = MayastorFeatures::get().into(); let reply = MayastorInfoRequest { version: raw_version_string(), diff --git a/io-engine/src/grpc/v1/host.rs b/io-engine/src/grpc/v1/host.rs index 72d871963..c270dd892 100644 --- a/io-engine/src/grpc/v1/host.rs +++ b/io-engine/src/grpc/v1/host.rs @@ -1,6 +1,6 @@ use crate::{ bdev::{nexus, NvmeControllerState}, - core::{BlockDeviceIoStats, CoreError, MayastorFeatures}, + core::{BlockDeviceIoStats, CoreError, MayastorBugFixes, MayastorFeatures}, grpc::{ controller_grpc::{ controller_stats, @@ -17,7 +17,10 @@ use crate::{ }; use ::function_name::named; use futures::FutureExt; -use io_engine_api::v1::{host as host_rpc, registration::RegisterRequest}; +use io_engine_api::{ + v1, + v1::{host as host_rpc, registration::RegisterRequest}, +}; use std::panic::AssertUnwindSafe; use tonic::{Request, Response, Status}; use version_info::raw_version_string; @@ -99,8 +102,23 @@ impl From for host_rpc::MayastorFeatures { fn from(f: MayastorFeatures) -> Self { Self { asymmetric_namespace_access: f.asymmetric_namespace_access, - logical_volume_manager: f.logical_volume_manager, - snapshot_rebuild: f.snapshot_rebuild, + logical_volume_manager: Some(f.logical_volume_manager), + snapshot_rebuild: Some(f.snapshot_rebuild), + } + } +} +impl From for host_rpc::BackCompatMayastorFeatures { + fn from(f: MayastorFeatures) -> Self { + Self { + asymmetric_namespace_access: f.asymmetric_namespace_access, + } + } +} + +impl From for host_rpc::MayastorBugFixes { + fn from(f: MayastorBugFixes) -> Self { + Self { + nexus_rebuild_replica_ancestry: f.nexus_rebuild_replica_ancestry, } } } @@ -220,20 +238,15 @@ impl host_rpc::HostRpc for HostService { &self, _request: Request<()>, ) -> GrpcResult { - let features = MayastorFeatures::get_features().into(); let api_versions = self .api_versions .iter() - .map(|v| { - let api_version: io_engine_api::v1::registration::ApiVersion = - v.clone().into(); - api_version as i32 - }) + .map(|v| v1::registration::ApiVersion::from(*v) as i32) .collect(); let response = host_rpc::MayastorInfoResponse { version: raw_version_string(), - supported_features: Some(features), + previous_features: Some(MayastorFeatures::get().into()), registration_info: Some(RegisterRequest { id: self.node_name.clone(), grpc_endpoint: self.grpc_socket.to_string(), @@ -241,6 +254,9 @@ impl host_rpc::HostRpc for HostService { .map(|r| r.instance_uuid().to_string()), api_version: api_versions, hostnqn: self.node_nqn.clone(), + features: Some(MayastorFeatures::get().into()), + bugfixes: Some(MayastorBugFixes::get().into()), + version: Some(raw_version_string()), }), }; diff --git a/io-engine/src/lvm/mod.rs b/io-engine/src/lvm/mod.rs index c33f50ab0..373820989 100644 --- a/io-engine/src/lvm/mod.rs +++ b/io-engine/src/lvm/mod.rs @@ -266,7 +266,7 @@ impl PoolFactory for PoolLvmFactory { &self, args: &FindPoolArgs, ) -> Result>, crate::pool_backend::Error> { - if !crate::core::MayastorFeatures::get_features().lvm() { + if !crate::core::MayastorFeatures::get().lvm() { return Ok(None); } use CmnQueryArgs; @@ -291,7 +291,7 @@ impl PoolFactory for PoolLvmFactory { &self, args: &ListPoolArgs, ) -> Result>, crate::pool_backend::Error> { - if !crate::core::MayastorFeatures::get_features().lvm() { + if !crate::core::MayastorFeatures::get().lvm() { return Ok(vec![]); } if matches!(args.backend, Some(p) if p != PoolBackend::Lvm) { @@ -340,7 +340,7 @@ impl ReplicaFactory for ReplLvmFactory { &self, args: &ListReplicaArgs, ) -> Result>, crate::pool_backend::Error> { - if !crate::core::MayastorFeatures::get_features().lvm() { + if !crate::core::MayastorFeatures::get().lvm() { return Ok(vec![]); } let replicas = LogicalVolume::list( diff --git a/io-engine/src/subsys/registration/registration_grpc.rs b/io-engine/src/subsys/registration/registration_grpc.rs index abf4398a2..6d3818c91 100644 --- a/io-engine/src/subsys/registration/registration_grpc.rs +++ b/io-engine/src/subsys/registration/registration_grpc.rs @@ -1,14 +1,17 @@ #![warn(missing_docs)] +use crate::core::{MayastorBugFixes, MayastorFeatures}; use futures::{select, FutureExt, StreamExt}; use http::Uri; use io_engine_api::v1::registration::{ registration_client, + ApiVersion as ApiVersionGrpc, DeregisterRequest, RegisterRequest, }; use once_cell::sync::OnceCell; use std::{env, str::FromStr, time::Duration}; +use version_info::raw_version_string; /// Mayastor sends registration messages in this interval (kind of heart-beat) const HB_INTERVAL_SEC: Duration = Duration::from_secs(5); @@ -19,7 +22,7 @@ const HTTP_KEEP_ALIVE_INTERVAL: Duration = Duration::from_secs(10); /// The http2 keep alive TIMEOUT. const HTTP_KEEP_ALIVE_TIMEOUT: Duration = Duration::from_secs(20); -#[derive(Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] /// ApiVersion to be supported pub enum ApiVersion { /// V0 Version of api @@ -152,31 +155,23 @@ impl Registration { /// Register a new node over rpc pub async fn register(&mut self) -> Result<(), tonic::Status> { - let api_versions = self - .config - .api_versions - .clone() - .into_iter() - .map(|v| { - let api_version: io_engine_api::v1::registration::ApiVersion = - v.into(); - api_version as i32 - }) - .collect(); - match self - .client - .register(tonic::Request::new(RegisterRequest { - id: self.config.node.to_string(), - grpc_endpoint: self.config.grpc_endpoint.clone(), - instance_uuid: Some(self.config.instance_uuid.to_string()), - api_version: api_versions, - hostnqn: self.config.node_nqn.clone(), - })) + let api_versions = self.config.api_versions.iter(); + let api_versions = + api_versions.map(|v| ApiVersionGrpc::from(*v) as i32); + let register = RegisterRequest { + id: self.config.node.to_string(), + grpc_endpoint: self.config.grpc_endpoint.clone(), + instance_uuid: Some(self.config.instance_uuid.to_string()), + api_version: api_versions.collect(), + hostnqn: self.config.node_nqn.clone(), + features: Some(MayastorFeatures::get().into()), + bugfixes: Some(MayastorBugFixes::get().into()), + version: Some(raw_version_string()), + }; + self.client + .register(tonic::Request::new(register)) .await - { - Ok(_) => Ok(()), - Err(e) => Err(e), - } + .map(|_| ()) } /// Deregister a node over rpc diff --git a/test/python/v1/pool/test_bdd_lvm.py b/test/python/v1/pool/test_bdd_lvm.py index 63502104d..cd42b5fc6 100644 --- a/test/python/v1/pool/test_bdd_lvm.py +++ b/test/python/v1/pool/test_bdd_lvm.py @@ -116,7 +116,7 @@ def find(name): @when("the user calls the gRPC mayastor info request", target_fixture="get_lvm_feature") def get_lvm_feature(get_mayastor_instance, get_mayastor_info): - return get_mayastor_info.supportedFeatures.logicalVolumeManager + return get_mayastor_info.registration_info.features.logicalVolumeManager @then("the instance shall report if it supports the LVM feature") diff --git a/utils/dependencies b/utils/dependencies index 8c977cb9a..eb9d43a61 160000 --- a/utils/dependencies +++ b/utils/dependencies @@ -1 +1 @@ -Subproject commit 8c977cb9a28696bdd502f57eb89029f9654f7376 +Subproject commit eb9d43a612604750de9679179d33058f2daf780b