Skip to content

Commit

Permalink
Try #710:
Browse files Browse the repository at this point in the history
  • Loading branch information
mayastor-bors committed Jan 12, 2024
2 parents d28c0ea + 8b46715 commit b64ba35
Show file tree
Hide file tree
Showing 12 changed files with 55 additions and 7 deletions.
4 changes: 2 additions & 2 deletions control-plane/agents/src/bin/core/volume/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ impl ResourceLifecycleExt<CreateVolume> for OperationGuardArc<VolumeSpec> {
) -> Result<Self::CreateOutput, SvcError> {
let specs = registry.specs();
let mut volume = specs
.get_or_create_volume(&CreateVolumeSource::None(request))
.get_or_create_volume(&CreateVolumeSource::None(request))?
.operation_guard_wait()
.await?;
let volume_clone = volume.start_create(registry, request).await?;
Expand Down Expand Up @@ -790,7 +790,7 @@ impl ResourceLifecycleExt<CreateVolumeSource<'_>> for OperationGuardArc<VolumeSp

let specs = registry.specs();
let mut volume = specs
.get_or_create_volume(request_src)
.get_or_create_volume(request_src)?
.operation_guard_wait()
.await?;
let volume_clone = volume.start_create_update(registry, request).await?;
Expand Down
22 changes: 18 additions & 4 deletions control-plane/agents/src/bin/core/volume/specs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,19 +748,33 @@ impl ResourceSpecsLocked {
pub(crate) fn get_or_create_volume(
&self,
request: &CreateVolumeSource,
) -> ResourceMutex<VolumeSpec> {
) -> Result<ResourceMutex<VolumeSpec>, SvcError> {
let mut specs = self.write();
if let Some(volume) = specs.volumes.get(&request.source().uuid) {
volume.clone()
Ok(volume.clone())
} else {
// if request has a capacity limit, add up the volumes and reject
// if the capacity limit would be exceeded
match request.source().capacity_limit {
None => {} // no limit, no check needed
Some(limit) => {
let mut total: u64 = request.source().size;
for vol in specs.volumes.to_vec() {
total += vol.lock().size;
if total > limit {
return Err(SvcError::CapacityLimitExceeded {});
}
}
}
}
match request {
CreateVolumeSource::None(_) => {
specs.volumes.insert(VolumeSpec::from(request.source()))
Ok(specs.volumes.insert(VolumeSpec::from(request.source())))
}
CreateVolumeSource::Snapshot(create_from_snap) => {
let mut spec = VolumeSpec::from(request.source());
spec.set_content_source(Some(create_from_snap.to_snapshot_source()));
specs.volumes.insert(spec)
Ok(specs.volumes.insert(spec))
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions control-plane/agents/src/common/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,8 @@ pub enum SvcError {
DrainNotAllowedWhenHAisDisabled {},
#[snafu(display("Target switchover is not allowed without HA"))]
SwitchoverNotAllowedWhenHAisDisabled {},
#[snafu(display("The volume would exceed the capacity limit"))]
CapacityLimitExceeded {},
}

impl SvcError {
Expand Down Expand Up @@ -934,6 +936,12 @@ impl From<SvcError> for ReplyError {
source,
extra,
},
SvcError::CapacityLimitExceeded {} => ReplyError {
kind: ReplyErrorKind::CapacityLimitExceeded,
resource: ResourceKind::Volume,
source,
extra,
},
}
}
}
Expand Down
1 change: 1 addition & 0 deletions control-plane/grpc/proto/v1/misc/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ enum ReplyErrorKind {
ReplicaCreateNumber = 27;
VolumeNoReplicas = 28;
InUse = 29;
CapacityLimitExceeded = 30;
}

// ResourceKind for the resource which has undergone this error
Expand Down
2 changes: 2 additions & 0 deletions control-plane/grpc/proto/v1/volume/volume.proto
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ message CreateVolumeRequest {
bool thin = 8;
// Affinity Group related information.
optional AffinityGroup affinity_group = 9;
// maximum total volume size
optional uint64 capacity_limit = 10;
}

// Publish a volume on a node
Expand Down
2 changes: 2 additions & 0 deletions control-plane/grpc/src/misc/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ impl From<ReplyErrorKind> for common::ReplyErrorKind {
ReplyErrorKind::ReplicaCreateNumber => Self::ReplicaCreateNumber,
ReplyErrorKind::VolumeNoReplicas => Self::VolumeNoReplicas,
ReplyErrorKind::InUse => Self::InUse,
ReplyErrorKind::CapacityLimitExceeded => Self::CapacityLimitExceeded,
}
}
}
Expand Down Expand Up @@ -135,6 +136,7 @@ impl From<common::ReplyErrorKind> for ReplyErrorKind {
common::ReplyErrorKind::ReplicaCreateNumber => Self::ReplicaCreateNumber,
common::ReplyErrorKind::VolumeNoReplicas => Self::VolumeNoReplicas,
common::ReplyErrorKind::InUse => Self::InUse,
common::ReplyErrorKind::CapacityLimitExceeded => Self::CapacityLimitExceeded,
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions control-plane/grpc/src/operations/volume/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,8 @@ pub trait CreateVolumeInfo: Send + Sync + std::fmt::Debug {
fn thin(&self) -> bool;
/// Affinity Group related information.
fn affinity_group(&self) -> Option<AffinityGroup>;
/// Capacity Limit
fn capacity_limit(&self) -> Option<u64>;
}

impl CreateVolumeInfo for CreateVolume {
Expand Down Expand Up @@ -924,6 +926,10 @@ impl CreateVolumeInfo for CreateVolume {
fn affinity_group(&self) -> Option<AffinityGroup> {
self.affinity_group.clone()
}

fn capacity_limit(&self) -> Option<u64> {
self.capacity_limit
}
}

/// Intermediate structure that validates the conversion to CreateVolumeRequest type.
Expand Down Expand Up @@ -972,6 +978,10 @@ impl CreateVolumeInfo for ValidatedCreateVolumeRequest {
fn affinity_group(&self) -> Option<AffinityGroup> {
self.inner.affinity_group.clone().map(|ag| ag.into())
}

fn capacity_limit(&self) -> Option<u64> {
self.inner.capacity_limit
}
}

impl ValidateRequestTypes for CreateVolumeRequest {
Expand Down Expand Up @@ -1008,6 +1018,7 @@ impl From<&dyn CreateVolumeInfo> for CreateVolume {
labels: data.labels(),
thin: data.thin(),
affinity_group: data.affinity_group(),
capacity_limit: data.capacity_limit(),
}
}
}
Expand All @@ -1025,6 +1036,7 @@ impl From<&dyn CreateVolumeInfo> for CreateVolumeRequest {
.map(|labels| crate::common::StringMapValue { value: labels }),
thin: data.thin(),
affinity_group: data.affinity_group().map(|ag| ag.into()),
capacity_limit: data.capacity_limit(),
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion control-plane/rest/openapi-specs/v0_api_spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2911,6 +2911,7 @@ components:
- FailedPersist
- Deleting
- InUse
- CapacityLimitExceeded
required:
- details
- kind
Expand Down Expand Up @@ -3826,4 +3827,4 @@ components:
content:
application/json:
schema:
$ref: '#/components/schemas/RestJsonError'
$ref: '#/components/schemas/RestJsonError'
1 change: 1 addition & 0 deletions control-plane/rest/src/versions/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ impl CreateVolumeBody {
labels: self.labels.clone(),
thin: self.thin,
affinity_group: self.affinity_group.clone(),
capacity_limit: None,
}
}
/// Convert into rpc request type.
Expand Down
1 change: 1 addition & 0 deletions control-plane/stor-port/src/transport_api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ pub enum ReplyErrorKind {
ReplicaCreateNumber,
VolumeNoReplicas,
InUse,
CapacityLimitExceeded,
}

impl From<tonic::Code> for ReplyErrorKind {
Expand Down
4 changes: 4 additions & 0 deletions control-plane/stor-port/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ impl From<ReplyError> for RestError<RestJsonError> {
let error = RestJsonError::new(details, message, Kind::FailedPrecondition);
(StatusCode::PRECONDITION_FAILED, error)
}
ReplyErrorKind::CapacityLimitExceeded => {
let error = RestJsonError::new(details, message, Kind::ResourceExhausted);
(StatusCode::INSUFFICIENT_STORAGE, error)
}
};

RestError::new(status, error)
Expand Down
2 changes: 2 additions & 0 deletions control-plane/stor-port/src/types/v0/transport/volume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,8 @@ pub struct CreateVolume {
pub thin: bool,
/// Affinity Group related information.
pub affinity_group: Option<AffinityGroup>,
/// Maximum total system volume size.
pub capacity_limit: Option<u64>,
}

/// Create volume request.
Expand Down

0 comments on commit b64ba35

Please sign in to comment.