[pbs-devel] [PATCH proxmox v4 2/3] pbs-api-types: extend datastore config by backend config enum
Christian Ebner
c.ebner at proxmox.com
Mon Jun 23 11:40:20 CEST 2025
Allows to configure a backend config variant for a datastore on
creation. The current default `Filesystem` backend variant is
introduced to be compatible with existing storages. A new S3 backend
variant allows to create datastores backed by an S3 compatible object
store instead.
For S3 backends, the type, id of the corresponding S3 client
configuration as well as the bucket name are stored as property
string. A valid datastore backend configuration for S3 therefore
contains:
```
...
backend bucket=<BUCKET_NAME>,client=<S3_CONFIG_ID>,type=s3
...
```
Signed-off-by: Christian Ebner <c.ebner at proxmox.com>
---
pbs-api-types/src/datastore.rs | 100 ++++++++++++++++++++++++++++++++-
1 file changed, 99 insertions(+), 1 deletion(-)
diff --git a/pbs-api-types/src/datastore.rs b/pbs-api-types/src/datastore.rs
index 5bd953ac..9efec432 100644
--- a/pbs-api-types/src/datastore.rs
+++ b/pbs-api-types/src/datastore.rs
@@ -286,6 +286,94 @@ pub const DATASTORE_TUNING_STRING_SCHEMA: Schema = StringSchema::new("Datastore
))
.schema();
+#[api]
+#[derive(Copy, Clone, Default, Deserialize, Serialize, Updater, PartialEq)]
+#[serde(rename_all = "kebab-case")]
+/// Datastore backend type
+pub enum DatastoreBackendType {
+ /// Local filesystem
+ #[default]
+ Filesystem,
+ /// S3 object store
+ S3,
+}
+serde_plain::derive_display_from_serialize!(DatastoreBackendType);
+serde_plain::derive_fromstr_from_deserialize!(DatastoreBackendType);
+
+#[api(
+ properties: {
+ type: {
+ type: DatastoreBackendType,
+ optional: true,
+ },
+ client: {
+ schema: super::s3::S3_CLIENT_ID_SCHEMA,
+ optional: true,
+ },
+ bucket: {
+ schema: super::s3::S3_BUCKET_NAME_SCHEMA,
+ optional: true,
+ },
+ },
+ default_key: "type",
+)]
+#[derive(Default, Deserialize, Serialize)]
+#[serde(rename_all = "kebab-case")]
+/// Datastore backend config
+pub struct DatastoreBackendConfig {
+ /// backend type
+ #[serde(rename = "type")]
+ pub ty: Option<DatastoreBackendType>,
+ /// s3 client id
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub client: Option<String>,
+ /// s3 bucket name
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub bucket: Option<String>,
+}
+
+pub const DATASTORE_BACKEND_CONFIG_STRING_SCHEMA: Schema =
+ StringSchema::new("Datastore backend config")
+ .format(&ApiStringFormat::VerifyFn(verify_datastore_backend_config))
+ .type_text("<backend-config>")
+ .schema();
+
+fn verify_datastore_backend_config(input: &str) -> Result<(), Error> {
+ DatastoreBackendConfig::from_str(input).map(|_| ())
+}
+
+impl FromStr for DatastoreBackendConfig {
+ type Err = Error;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let backend_config: DatastoreBackendConfig =
+ proxmox_schema::property_string::parse_with_schema(
+ s,
+ &DatastoreBackendConfig::API_SCHEMA,
+ )?;
+ let backend_type = backend_config.ty.unwrap_or_default();
+ match backend_type {
+ DatastoreBackendType::Filesystem => {
+ if backend_config.client.is_some() {
+ bail!("additional option client, not allowed for backend type filesystem");
+ }
+ if backend_config.bucket.is_some() {
+ bail!("additional option bucket, not allowed for backend type filesystem");
+ }
+ }
+ DatastoreBackendType::S3 => {
+ if backend_config.client.is_none() {
+ bail!("missing option client, required for backend type s3");
+ }
+ if backend_config.bucket.is_none() {
+ bail!("missing option bucket, required for backend type s3");
+ }
+ }
+ }
+ Ok(backend_config)
+ }
+}
+
#[api(
properties: {
name: {
@@ -336,7 +424,11 @@ pub const DATASTORE_TUNING_STRING_SCHEMA: Schema = StringSchema::new("Datastore
optional: true,
format: &proxmox_schema::api_types::UUID_FORMAT,
type: String,
- }
+ },
+ backend: {
+ schema: DATASTORE_BACKEND_CONFIG_STRING_SCHEMA,
+ optional: true,
+ },
}
)]
#[derive(Serialize, Deserialize, Updater, Clone, PartialEq)]
@@ -389,6 +481,11 @@ pub struct DataStoreConfig {
#[updater(skip)]
#[serde(skip_serializing_if = "Option::is_none")]
pub backing_device: Option<String>,
+
+ /// Backend configuration for datastore
+ #[updater(skip)]
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub backend: Option<String>,
}
#[api]
@@ -424,6 +521,7 @@ impl DataStoreConfig {
tuning: None,
maintenance_mode: None,
backing_device: None,
+ backend: None,
}
}
--
2.47.2
More information about the pbs-devel
mailing list