Skip to content

Commit

Permalink
feat(lvm): add lvm pool and replica support
Browse files Browse the repository at this point in the history
Add LVM as an experimental alternative backend to Mayastor:
1. it allows us to use a low latency single replica
local volume (app pinned to the same node)
2. robust backend for existing LVM users which may prefer it
3. combine local engines into mayastor

This differs from the existing lvm localpv as rather than importing
the existing VGs we create the LVM PV's and the LVM VG itself.
On destruction, if the VG has no non-mayastor LVs then we destroy it,
otherwise we leave it behind, untagged.

The existing pool/replica services are also refactored to support
adding other backends in the future as well.
This is achieved by implementing the service interface separately
and binding them at a higher level. This way it avoids mixing
the backend code, at least as much as possible.

Co-authored-by: shubham <[email protected]>
Co-authored-by: Akhil Mohan <[email protected]>
Co-authored-by: Tiago Castro <[email protected]>
Signed-off-by: Tiago Castro <[email protected]>
  • Loading branch information
3 people committed Apr 18, 2024
1 parent f997677 commit 2e46ef2
Show file tree
Hide file tree
Showing 59 changed files with 4,496 additions and 710 deletions.
2 changes: 2 additions & 0 deletions ci.nix
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ mkShell {
SPDK_PATH = if nospdk then null else "${spdk}";
FIO_SPDK = if nospdk then null else "${spdk}/fio/spdk_nvme";
ETCD_BIN = "${etcd}/bin/etcd";
LVM_BINS = "${lvm2.bin}/bin";

IO_ENGINE_DIR = if asan then "target/x86_64-unknown-linux-gnu/debug" else "target/debug";

Expand Down Expand Up @@ -102,6 +103,7 @@ mkShell {
${pkgs.lib.optionalString (!nospdk) "echo 'SPDK version :' $(echo $SPDK_PATH | sed 's/.*libspdk-//g')"}
${pkgs.lib.optionalString (!nospdk) "echo 'SPDK path :' $SPDK_PATH"}
${pkgs.lib.optionalString (!nospdk) "echo 'SPDK FIO plugin :' $FIO_SPDK"}
echo 'LVM path :' $LVM_BINS
${pkgs.lib.optionalString (!norust) "echo 'Rust version :' $(rustc --version 2> /dev/null || echo '${norustc_msg}')"}
${pkgs.lib.optionalString (!norust) "echo 'Rust path :' $(which rustc 2> /dev/null || echo '${norustc_msg}')"}
echo 'I/O engine dir :' $IO_ENGINE_DIR
Expand Down
109 changes: 109 additions & 0 deletions doc/lvm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# LVM as an alternative backend to Mayastor (Experimental!)

Mayastor, a cloud-native declarative data plane written in Rust, aims to abstract storage resources
and their differences through the data plane.

In this document, we’ll explore how to integrate Logical Volume Management (LVM) as an alternative
backend for Mayastor pools.
LVM, a mature and widely adopted storage management system in Linux environments, offers robustness
and extensive features that can enhance Mayastor’s storage services.

## Motivation

LVM is a mature and widely adopted storage management system in Linux environments.
While the SPDK Blobstore (LVS) has been a reliable option, integrating LVM as an alternative backend
can captivate a broader audience due to its robustness and maturity, feature set,
and community support make it an attractive choice for Mayastor users.
By integrating LVM, we can also allow users to upgrade existing non-replicated LVM volumes
(eg: lvm-localpv) seamlessly.

## Goals

Alternative Backend: Enable Mayastor to use LVM volume groups as an alternative backend for storage
pools.
Dynamic Volume Management: Leverage LVM’s volume management features (resizing, snapshots,
thin provisioning) within Mayastor.
Simplicity: Abstract LVM complexities from users while providing robust storage services.

### Supporting Changes
1. Pools

Mayastor pools represent devices supplying persistent backing storage.
Introduce a new pool type: LVM Pool.
Users can create new Mayastor pools with the LVM backend type.

2. LVM Integration

Extend Mayastor to integrate with LVM.
Implement LVM-specific logic for pool and replica creation, replica resizing, and snapshot management.
Ensure seamless interaction between Mayastor and LVM.

3. Replication (HA)

Extend Mayastor’s replication mechanisms to work with LVM-backed logical units.
In short, make LVM backed volumes highly available across nodes.

4. Volume Management

Mayastor will expose LVM volume management features through its pool API.
Users can resize volumes online.
Snapshots are managed transparently.

Features
---

- [x] Pool Operations
- [x] Create
- [x] Destroy
- [x] Import
- [x] List
- [x] Replica Operations
- [x] Create
- [x] Destroy
- [x] Share/Unshare
- [x] Resize
- [x] List
- [ ] Thin Provisioning
- [ ] Snapshots
- [ ] Clones
- [ ] RAIDx

### Limitation
- Thin provisioning and snapshot support is not yet integrated
- RAID is not yet integrated

## Conclusion

By integrating LVM with Mayastor, you can leverage the benefits of both technologies. LVM provides dynamic volume management,
while Mayastor abstracts storage complexities, allowing you to focus on your applications.
Happy storage provisioning! 🚀


```mermaid
graph TD;
subgraph Volume Group - VG
VG_1 --> LV_1["replica 1"]
VG_1 --> LV_2["replica 2"]
VG_2 --> LV_3["replica 3"]
end
subgraph Mayastor Volume
LV_1 --> VOL_1["1-replica volume"]
LV_2 --> VOL_2["2-replica volume"]
LV_3 --> VOL_2["2-replica volume"]
end
subgraph Physical Volumes
PV_1 --> VG_1["Volume Group - VG 1"]
PV_2 --> VG_1
PV_3 --> VG_2["Volume Group - VG 2"]
end
subgraph Node1
/dev/sda --> PV_1
/dev/sdb --> PV_2
end
subgraph Node2
/dev/sdc --> PV_3
end
```
2 changes: 1 addition & 1 deletion io-engine-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ url = "2.4.1"
composer = { path = "../utils/dependencies/composer" }
libnvme-rs = { path = "../libnvme-rs" }
io-engine-api = { path = "../utils/dependencies/apis/io-engine" }
version-info = { path = "../utils/dependencies/version-info" }
version-info = { path = "../utils/dependencies/version-info", features = ["deps-logs-head"] }
io-engine = { path = "../io-engine" }
io-engine-tests-macros = { path = "./io-engine-tests-macros" }

Expand Down
1 change: 1 addition & 0 deletions io-engine-tests/src/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ impl PoolBuilder {
uuid: None,
pooluuid: self.uuid.clone(),
query: None,
pooltypes: vec![],
})
.await
.map(|r| r.into_inner().replicas)
Expand Down
2 changes: 2 additions & 0 deletions io-engine-tests/src/replica.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ pub async fn list_replicas(
uuid: None,
pooluuid: None,
query: None,
pooltypes: vec![],
})
.await
.map(|r| r.into_inner().replicas)
Expand All @@ -246,6 +247,7 @@ pub async fn find_replica_by_uuid(
uuid: Some(uuid.to_owned()),
pooluuid: None,
query: None,
pooltypes: vec![],
})
.await
.map(|r| r.into_inner().replicas)?
Expand Down
2 changes: 1 addition & 1 deletion io-engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ jsonrpc = { path = "../jsonrpc"}
io-engine-api = { path = "../utils/dependencies/apis/io-engine" }
spdk-rs = { path = "../spdk-rs" }
sysfs = { path = "../sysfs" }
version-info = { path = "../utils/dependencies/version-info" }
version-info = { path = "../utils/dependencies/version-info", features = ["deps-logs-head"] }
events-api = { path = "../utils/dependencies/apis/events" }
event-publisher = { path = "../utils/dependencies/event-publisher" }
tracing-filter = { path = "../utils/dependencies/tracing-filter" }
Expand Down
3 changes: 2 additions & 1 deletion io-engine/src/bdev/lvs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use crate::{
bdev_api::BdevError,
core::LogicalVolume,
lvs::LvsLvol,
pool_backend::PoolArgs,
pool_backend::{PoolArgs, PoolBackend},
};

/// An lvol specified via URI.
Expand Down Expand Up @@ -215,6 +215,7 @@ impl Lvs {
disks: vec![self.disk.to_owned()],
uuid: None,
cluster_size: None,
backend: PoolBackend::Lvs,
};
match &self.mode {
LvsMode::Create => {
Expand Down
6 changes: 6 additions & 0 deletions io-engine/src/bin/io-engine-client/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use byte_unit::Byte;
use snafu::{Backtrace, Snafu};
use strum::ParseError;
use tonic::transport::Channel;

use io_engine_api::v0::{
Expand All @@ -23,6 +24,11 @@ pub enum ClientError {
source: tonic::Status,
backtrace: Backtrace,
},
#[snafu(display("gRPC status: {}", source))]
GrpcParseStatus {
source: ParseError,
backtrace: Backtrace,
},
#[snafu(display("Context building error: {}", source))]
ContextCreate {
source: context::Error,
Expand Down
Loading

0 comments on commit 2e46ef2

Please sign in to comment.