Skip to content

Commit

Permalink
chore(bors): merge pull request #656
Browse files Browse the repository at this point in the history
656: feat(snapshots, restores): store restores as a part of snap meta, expose counts on rest r=Abhinandan-Purkait a=Abhinandan-Purkait

```
rest-plugin get volumes              
 ID                                    REPLICAS  TARGET-NODE  ACCESSIBILITY  STATUS  SIZE   THIN-PROVISIONED  ALLOCATED  SNAPSHOTS  SOURCE 
 ec4e66fd-3b33-4439-b504-d49aba53da26  1         <none>       <none>         Online  10MiB  true (snapped)    12MiB      1          <none> 
 ec4e66fd-3b33-4439-b504-d49aba53da27  1         <none>       <none>         Online  10MiB  true              12MiB      0          Snapshot 
 ec4e66fd-3b33-4439-b504-d49aba53da28  1         <none>       <none>         Online  10MiB  true              12MiB      0          Snapshot 
```
```
rest-plugin get volumes --source none
 ID                                    REPLICAS  TARGET-NODE  ACCESSIBILITY  STATUS  SIZE   THIN-PROVISIONED  ALLOCATED  SNAPSHOTS  SOURCE 
 ec4e66fd-3b33-4439-b504-d49aba53da26  1         <none>       <none>         Online  10MiB  true (snapped)    12MiB      1          <none> 
```
```
rest-plugin get volumes --source snapshot
 ID                                    REPLICAS  TARGET-NODE  ACCESSIBILITY  STATUS  SIZE   THIN-PROVISIONED  ALLOCATED  SNAPSHOTS  SOURCE 
 ec4e66fd-3b33-4439-b504-d49aba53da27  1         <none>       <none>         Online  10MiB  true              12MiB      0          Snapshot 
 ec4e66fd-3b33-4439-b504-d49aba53da28  1         <none>       <none>         Online  10MiB  true              12MiB      0          Snapshot
```

Co-authored-by: Abhinandan Purkait <[email protected]>
  • Loading branch information
mayastor-bors and Abhinandan-Purkait committed Aug 11, 2023
2 parents bd486c0 + 25ca7f6 commit 179bc4e
Show file tree
Hide file tree
Showing 21 changed files with 325 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::controller::registry::Registry;
use crate::controller::{registry::Registry, resources::OperationGuardArc};
use agents::errors::SvcError;
use stor_port::types::v0::store::volume::VolumeSpec;

/// Resource Cordon Operations.
#[async_trait::async_trait]
Expand Down Expand Up @@ -265,11 +266,20 @@ pub(crate) trait ResourcePruning {
pub(crate) trait ResourceCloning {
type Create: Sync + Send;
type CreateOutput: Sync + Send + Sized;
type Destroy: Sync + Send;

/// Create a clone for the `Self` resource.
async fn create_clone(
&mut self,
registry: &Registry,
request: &Self::Create,
) -> Result<Self::CreateOutput, SvcError>;

/// Destroy a clone for the `Self` resource, using the volume life cycle op.
async fn destroy_clone(
&mut self,
registry: &Registry,
request: &Self::Destroy,
volume: OperationGuardArc<VolumeSpec>,
) -> Result<(), SvcError>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ use std::{fmt::Debug, ops::Deref, sync::Arc};
use stor_port::{
pstor::{product_v1_key_prefix, API_VERSION},
transport_api::ErrorChain,
types::v0::{store::snapshots::volume::VolumeSnapshot, transport::SnapshotId},
types::v0::{
store::{snapshots::volume::VolumeSnapshot, volume::VolumeContentSource},
transport::SnapshotId,
},
};

#[derive(Debug, Snafu)]
Expand Down Expand Up @@ -939,6 +942,18 @@ impl ResourceSpecsLocked {
}
}

// add runtime information for volume restores
for volume in self.read().volumes.values() {
match volume.immutable_ref().content_source.as_ref() {
None => continue,
Some(VolumeContentSource::Snapshot(snap_uuid, _)) => {
if let Some(snapshot) = self.read().volume_snapshots.get(snap_uuid) {
snapshot.lock().insert_restore(volume.uuid())
}
}
}
}

// Remove all entries of v1 key prefix.
store
.delete_values_prefix(&product_v1_key_prefix())
Expand Down
4 changes: 2 additions & 2 deletions control-plane/agents/src/bin/core/tests/pool/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,8 +550,8 @@ async fn reconciler_missing_pool_state() {
.with_agents(vec!["core"])
.with_io_engines(1)
.with_pool(0, disk.uri())
.with_cache_period("1s")
.with_reconcile_period(Duration::from_secs(1), Duration::from_secs(1))
.with_cache_period("500ms")
.with_reconcile_period(Duration::from_millis(500), Duration::from_millis(500))
.build()
.await
.unwrap();
Expand Down
50 changes: 45 additions & 5 deletions control-plane/agents/src/bin/core/volume/clone_operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::{
controller::{
registry::Registry,
resources::{
operations::{ResourceCloning, ResourceLifecycleExt},
operations_helper::SpecOperationsHelper,
operations::{ResourceCloning, ResourceLifecycle, ResourceLifecycleExt},
operations_helper::{GuardedOperationsHelper, SpecOperationsHelper},
OperationGuardArc, TraceStrLog,
},
scheduling::{volume::CloneVolumeSnapshot, ResourceFilter},
Expand All @@ -16,11 +16,13 @@ use stor_port::{
types::v0::{
store::{
replica::ReplicaSpec,
snapshots::volume::VolumeSnapshot,
snapshots::volume::{
CreateRestoreInfo, DestroyRestoreInfo, VolumeSnapshot, VolumeSnapshotOperation,
},
volume::{VolumeContentSource, VolumeSpec},
},
transport::{
CreateSnapshotVolume, Replica, SnapshotCloneId, SnapshotCloneParameters,
CreateSnapshotVolume, DestroyVolume, Replica, SnapshotCloneId, SnapshotCloneParameters,
SnapshotCloneSpecParams,
},
},
Expand All @@ -45,14 +47,52 @@ impl SnapshotCloneOp<'_> {
impl ResourceCloning for OperationGuardArc<VolumeSnapshot> {
type Create = CreateSnapshotVolume;
type CreateOutput = OperationGuardArc<VolumeSpec>;
type Destroy = DestroyVolume;

async fn create_clone(
&mut self,
registry: &Registry,
request: &Self::Create,
) -> Result<Self::CreateOutput, SvcError> {
let spec_clone = self
.start_update(
registry,
self.as_ref(),
VolumeSnapshotOperation::CreateRestore(CreateRestoreInfo::new(
request.params().uuid.clone(),
)),
)
.await?;
let request = CreateVolumeSource::Snapshot(SnapshotCloneOp(request, self));
OperationGuardArc::<VolumeSpec>::create_ext(registry, &request).await

// Create the restore using the volume op guard.
let create_result = OperationGuardArc::<VolumeSpec>::create_ext(registry, &request).await;

self.complete_update(registry, create_result, spec_clone)
.await
}

async fn destroy_clone(
&mut self,
registry: &Registry,
request: &Self::Destroy,
mut volume: OperationGuardArc<VolumeSpec>,
) -> Result<(), SvcError> {
let spec_clone = self
.start_update(
registry,
self.as_ref(),
VolumeSnapshotOperation::DestroyRestore(DestroyRestoreInfo::new(
request.uuid.clone(),
)),
)
.await?;

// Destroy the restore using the volume op guard.
let destroy_result = volume.destroy(registry, request).await;

self.complete_update(registry, destroy_result, spec_clone)
.await
}
}

Expand Down
27 changes: 24 additions & 3 deletions control-plane/agents/src/bin/core/volume/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ use grpc::{
use stor_port::{
transport_api::{v0::Volumes, ReplyError, ResourceKind},
types::v0::{
store::{snapshots::volume::VolumeSnapshotUserSpec, volume::VolumeSpec},
store::{
snapshots::volume::VolumeSnapshotUserSpec,
volume::{VolumeContentSource, VolumeSpec},
},
transport::{
CreateSnapshotVolume, CreateVolume, DestroyShutdownTargets, DestroyVolume, Filter,
PublishVolume, RepublishVolume, SetVolumeReplica, ShareVolume, UnpublishVolume,
Expand Down Expand Up @@ -298,8 +301,26 @@ impl Service {
#[tracing::instrument(level = "info", skip(self), err, fields(volume.uuid = %request.uuid))]
pub(super) async fn destroy_volume(&self, request: &DestroyVolume) -> Result<(), SvcError> {
let mut volume = self.specs().volume(&request.uuid).await?;
volume.destroy(&self.registry, request).await?;
Ok(())
let content_source = volume.as_ref().content_source.as_ref();
let snap_guard = match content_source {
None => None,
Some(VolumeContentSource::Snapshot(snap_uuid, _)) => {
match self.specs().volume_snapshot(snap_uuid).await {
Ok(snap_guard) => Some(snap_guard),
Err(SvcError::VolSnapshotNotFound { .. }) => None,
Err(error) => return Err(error),
}
}
};

match snap_guard {
None => volume.destroy(&self.registry, request).await,
Some(mut snap_guard) => {
snap_guard
.destroy_clone(&self.registry, request, volume)
.await
}
}
}

/// Destroy the shutdown targets associate with the volume.
Expand Down
4 changes: 4 additions & 0 deletions control-plane/grpc/proto/v1/volume/volume.proto
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ message VolumeSpec {
optional AffinityGroup affinity_group = 10;
// Volume Content Source i.e the snapshot or a volume.
optional VolumeContentSource content_source = 11;
// Number of snapshots taken on this volume.
uint32 num_snapshots = 12;

// Volume Content Source i.e the snapshot or a volume.
message VolumeContentSource {
Expand Down Expand Up @@ -507,6 +509,8 @@ message VolumeSnapshotMeta {
uint64 spec_size = 6;
// Size taken by the snapshot and its predecessors.
uint64 total_allocated_size = 7;
// Number of restores done from this snapshot.
uint32 num_restores = 8;

message ReplicaSnapshots {
repeated ReplicaSnapshot snapshots = 1;
Expand Down
2 changes: 2 additions & 0 deletions control-plane/grpc/src/operations/volume/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ impl From<VolumeSpec> for volume::VolumeDefinition {
thin: volume_spec.thin,
affinity_group: volume_spec.affinity_group.into_opt(),
content_source: volume_spec.content_source.into_opt(),
num_snapshots: volume_spec.metadata.num_snapshots() as u32,
}),
metadata: Some(volume::Metadata {
spec_status: spec_status as i32,
Expand Down Expand Up @@ -318,6 +319,7 @@ impl TryFrom<volume::VolumeDefinition> for VolumeSpec {
affinity_group: volume_spec.affinity_group.into_opt(),
metadata: VolumeMetadata::new(volume_meta.as_thin),
content_source: volume_spec.content_source.try_into_opt()?,
num_snapshots: volume_spec.num_snapshots,
};
Ok(volume_spec)
}
Expand Down
10 changes: 10 additions & 0 deletions control-plane/grpc/src/operations/volume/traits_snapshots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ impl From<&stor_port::types::v0::store::snapshots::volume::VolumeSnapshot> for V
total_allocated_size: value.metadata().total_allocated_size(),
txn_id: value.metadata().txn_id().clone(),
transactions,
num_restores: value.num_restores(),
},
}
}
Expand Down Expand Up @@ -137,7 +138,10 @@ pub struct VolumeSnapshotMeta {
/// The "actual" snapshots can be accessed by the key `txn_id`.
/// Failed transactions are any other key.
transactions: HashMap<String, Vec<ReplicaSnapshot>>,
/// The number of restores done from this snapshot.
num_restores: u32,
}

impl VolumeSnapshotMeta {
/// Get the volume snapshot status.
pub fn status(&self) -> &SpecStatus<()> {
Expand Down Expand Up @@ -167,6 +171,10 @@ impl VolumeSnapshotMeta {
pub fn total_allocated_size(&self) -> u64 {
self.total_allocated_size
}
/// The number of restores done from this snapshot.
pub fn num_restores(&self) -> u32 {
self.num_restores
}
}

/// Volume replica snapshot information.
Expand Down Expand Up @@ -468,6 +476,7 @@ impl TryFrom<volume::VolumeSnapshot> for VolumeSnapshot {
snapshots.map(|s| (k, s))
})
.collect::<Result<HashMap<_, _>, _>>()?,
num_restores: meta.num_restores,
},
state: VolumeSnapshotState {
info,
Expand Down Expand Up @@ -624,6 +633,7 @@ impl TryFrom<VolumeSnapshot> for volume::VolumeSnapshot {
size: value.meta.size,
spec_size: value.meta.spec_size,
total_allocated_size: value.meta.total_allocated_size,
num_restores: value.meta.num_restores,
}),
state: Some(volume::VolumeSnapshotState {
state: Some(snapshot::SnapshotState {
Expand Down
12 changes: 7 additions & 5 deletions control-plane/plugin/src/bin/rest-plugin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use clap::Parser;
use openapi::tower::client::Url;
use plugin::{
operations::{
Cordoning, Drain, Get, GetBlockDevices, GetSnapshots, List, Operations, RebuildHistory,
ReplicaTopology, Scale,
Cordoning, Drain, Get, GetBlockDevices, GetSnapshots, List, ListExt, Operations,
RebuildHistory, ReplicaTopology, Scale,
},
resources::{
blockdevice, cordon, drain, node, pool, snapshot, volume, CordonResources, DrainResources,
Expand Down Expand Up @@ -83,13 +83,15 @@ async fn execute(cli_args: CliArgs) {
}
GetDrainArgs::Nodes => drain::NodeDrains::list(&cli_args.output).await,
},
GetResources::Volumes => volume::Volumes::list(&cli_args.output).await,
GetResources::Volumes(vol_args) => {
volume::Volumes::list(&cli_args.output, vol_args).await
}
GetResources::Volume { id } => volume::Volume::get(id, &cli_args.output).await,
GetResources::RebuildHistory { id } => {
volume::Volume::rebuild_history(id, &cli_args.output).await
}
GetResources::VolumeReplicaTopologies => {
volume::Volume::topologies(&cli_args.output).await
GetResources::VolumeReplicaTopologies(vol_args) => {
volume::Volume::topologies(&cli_args.output, vol_args).await
}
GetResources::VolumeReplicaTopology { id } => {
volume::Volume::topology(id, &cli_args.output).await
Expand Down
11 changes: 10 additions & 1 deletion control-plane/plugin/src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ pub trait List {
async fn list(output: &utils::OutputFormat);
}

/// List trait.
/// To be implemented by resources which support the 'list' operation, with context.
#[async_trait(?Send)]
pub trait ListExt {
type Context;
async fn list(output: &utils::OutputFormat, context: &Self::Context);
}

/// Get trait.
/// To be implemented by resources which support the 'get' operation.
#[async_trait(?Send)]
Expand All @@ -62,7 +70,8 @@ pub trait Scale {
#[async_trait(?Send)]
pub trait ReplicaTopology {
type ID;
async fn topologies(output: &utils::OutputFormat);
type Context;
async fn topologies(output: &utils::OutputFormat, context: &Self::Context);
async fn topology(id: &Self::ID, output: &utils::OutputFormat);
}

Expand Down
5 changes: 3 additions & 2 deletions control-plane/plugin/src/resources/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::resources::{
blockdevice::BlockDeviceArgs,
node::{DrainNodeArgs, GetNodeArgs},
snapshot::VolumeSnapshotArgs,
volume::VolumesArgs,
};

pub mod blockdevice;
Expand Down Expand Up @@ -29,13 +30,13 @@ pub enum GetResources {
#[clap(subcommand)]
Drain(GetDrainArgs),
/// Get all volumes.
Volumes,
Volumes(VolumesArgs),
/// Get volume with the given ID.
Volume { id: VolumeId },
/// Get Rebuild history for the volume with the given ID.
RebuildHistory { id: VolumeId },
/// Get the replica topology for all volumes.
VolumeReplicaTopologies,
VolumeReplicaTopologies(VolumesArgs),
/// Get the replica topology for the volume with the given ID.
VolumeReplicaTopology { id: VolumeId },
/// Get volume snapshots based on input args.
Expand Down
3 changes: 2 additions & 1 deletion control-plane/plugin/src/resources/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ impl CreateRow for openapi::models::VolumeSnapshot {
::utils::bytes::into_human(meta.spec_size),
::utils::bytes::into_human(state.allocated_size),
::utils::bytes::into_human(meta.total_allocated_size),
state.source_volume
state.source_volume,
self.definition.metadata.num_restores
]
}
}
Expand Down
7 changes: 5 additions & 2 deletions control-plane/plugin/src/resources/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,18 @@ lazy_static! {
"STATUS",
"SIZE",
"THIN-PROVISIONED",
"ALLOCATED"
"ALLOCATED",
"SNAPSHOTS",
"SOURCE"
];
pub static ref SNAPSHOT_HEADERS: Row = row![
"ID",
"TIMESTAMP",
"SOURCE-SIZE",
"ALLOCATED-SIZE",
"TOTAL-ALLOCATED-SIZE",
"SOURCE-VOL"
"SOURCE-VOL",
"RESTORES"
];
pub static ref POOLS_HEADERS: Row = row![
"ID",
Expand Down
Loading

0 comments on commit 179bc4e

Please sign in to comment.