* [PATCH common/proxmox{,-backup}/storage v2 0/9] establish unique instance-id for PBS nodes
@ 2026-04-24 8:29 Lukas Wagner
2026-04-24 8:29 ` [PATCH proxmox v2 1/9] pbs-api-types: add ServerIdentity response type Lukas Wagner
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: Lukas Wagner @ 2026-04-24 8:29 UTC (permalink / raw)
To: pbs-devel, pve-devel
In PDM we require some way to match PBS storage <-> PBS remote.
Having some kind of unique ID for each PBS instance should make it quite easy
to establish such a mapping completely automatically.
The general approach is
1.) add /nodes/localhost/server-identity route in PBS, returning a unique, per-installation ID
2.) add something like /nodes/.../storage/<id>/identity in PVE, which uses
proxmox-backup-client internally to return the instance ID for this PBS storage
3.) PDM can then use both API routes to establish the mapping
Changes since v1:
- Rebased the proxmox-backup part (@thx Chris)
- the pve-storage part is now implemented as a method in the storage plugin,
`get_identity` (thx @Thomas)
- the identity route now return the type of the plugin as well as a discriminant
- the route in PBS has been renamed to just /nodes/localhost/identity (thx @thomas)
Significant changes since the RFC:
- fixup copy-paste doc mistakes (thx @ Shannon)
- in PVE, the API is now '/nodes/<node>/storage/<id>/identity', as this is hopefully
generic enough that it could be used for other storages enough.
- in PBS, the API is now at /nodes/localhost/server-identity
- in the Perl PBSClient, the method to retrieve the identity is now "get_server_identity"
proxmox:
Fabian Grünbichler (1):
systemd: add support for machine-id generation
Lukas Wagner (1):
pbs-api-types: add ServerIdentity response type
pbs-api-types/src/node.rs | 9 +++++
proxmox-systemd/src/lib.rs | 2 +
proxmox-systemd/src/sd_id128.rs | 70 +++++++++++++++++++++++++++++++++
proxmox-systemd/src/sys.rs | 6 +++
4 files changed, 87 insertions(+)
create mode 100644 proxmox-systemd/src/sd_id128.rs
proxmox-backup:
Lukas Wagner (3):
api: add /nodes/localhost/identity
client: add 'server-identity' sub-command
manager: add 'server-identity' subcommand
proxmox-backup-client/src/main.rs | 42 ++++++++++++++++++++++++--
src/api2/node/mod.rs | 40 ++++++++++++++++++++++--
src/bin/proxmox_backup_manager/node.rs | 30 ++++++++++++++++++
3 files changed, 107 insertions(+), 5 deletions(-)
pve-common:
Lukas Wagner (1):
pbs-client: add support for the 'server-identity' command
src/PVE/PBSClient.pm | 7 +++++++
1 file changed, 7 insertions(+)
pve-storage:
Lukas Wagner (3):
plugin: add get_identity method
bump storage plugin APIVER and reset APIAGE
api: add /nodes/<node>/storage/<storage>/identity route
src/PVE/API2/Storage/Status.pm | 57 +++++++++++++++++++++++++++++++++-
src/PVE/Storage.pm | 4 +--
src/PVE/Storage/PBSPlugin.pm | 9 ++++++
src/PVE/Storage/Plugin.pm | 17 ++++++++++
4 files changed, 84 insertions(+), 3 deletions(-)
Summary over all repositories:
12 files changed, 285 insertions(+), 8 deletions(-)
--
Generated by murpp 0.12.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH proxmox v2 1/9] pbs-api-types: add ServerIdentity response type
2026-04-24 8:29 [PATCH common/proxmox{,-backup}/storage v2 0/9] establish unique instance-id for PBS nodes Lukas Wagner
@ 2026-04-24 8:29 ` Lukas Wagner
2026-04-24 8:29 ` [PATCH proxmox v2 2/9] systemd: add support for machine-id generation Lukas Wagner
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Lukas Wagner @ 2026-04-24 8:29 UTC (permalink / raw)
To: pbs-devel, pve-devel
This type will be used to uniquely identify a PBS node, which comes in
useful to match PBS storages to PBS remotes in PDM.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
pbs-api-types/src/node.rs | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/pbs-api-types/src/node.rs b/pbs-api-types/src/node.rs
index da3e4118..73f8bd91 100644
--- a/pbs-api-types/src/node.rs
+++ b/pbs-api-types/src/node.rs
@@ -453,3 +453,12 @@ impl Iterator for AcmeDomainIter<'_> {
)
}
}
+
+#[api]
+#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
+#[serde(rename_all = "kebab-case")]
+/// Unique instance identity information.
+pub struct ServerIdentity {
+ /// Unique instance identifier.
+ pub pbs_instance_id: String,
+}
--
2.47.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH proxmox v2 2/9] systemd: add support for machine-id generation
2026-04-24 8:29 [PATCH common/proxmox{,-backup}/storage v2 0/9] establish unique instance-id for PBS nodes Lukas Wagner
2026-04-24 8:29 ` [PATCH proxmox v2 1/9] pbs-api-types: add ServerIdentity response type Lukas Wagner
@ 2026-04-24 8:29 ` Lukas Wagner
2026-04-24 8:29 ` [PATCH proxmox-backup v2 3/9] api: add /nodes/localhost/identity Lukas Wagner
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Lukas Wagner @ 2026-04-24 8:29 UTC (permalink / raw)
To: pbs-devel, pve-devel
From: Fabian Grünbichler <f.gruenbichler@proxmox.com>
the plain machine-id should not be leaked to external systems, but libsystemd
provides helpers for deriving application-id based identifiers that are useful
for identifying a machine externally.
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
proxmox-systemd/src/lib.rs | 2 +
proxmox-systemd/src/sd_id128.rs | 70 +++++++++++++++++++++++++++++++++
proxmox-systemd/src/sys.rs | 6 +++
3 files changed, 78 insertions(+)
create mode 100644 proxmox-systemd/src/sd_id128.rs
diff --git a/proxmox-systemd/src/lib.rs b/proxmox-systemd/src/lib.rs
index 456d88c3..f79c204c 100644
--- a/proxmox-systemd/src/lib.rs
+++ b/proxmox-systemd/src/lib.rs
@@ -7,3 +7,5 @@ pub use escape::{escape_unit, unescape_unit, unescape_unit_path, UnescapeError};
pub mod journal;
pub mod notify;
+
+pub mod sd_id128;
diff --git a/proxmox-systemd/src/sd_id128.rs b/proxmox-systemd/src/sd_id128.rs
new file mode 100644
index 00000000..a98a6663
--- /dev/null
+++ b/proxmox-systemd/src/sd_id128.rs
@@ -0,0 +1,70 @@
+use std::fmt;
+
+use crate::sys::{self, sd_id128_t};
+
+#[derive(Debug, PartialEq, Eq)]
+pub enum SystemdId128Error {
+ InvalidAppId,
+ GenerationError,
+}
+
+impl std::error::Error for SystemdId128Error {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ None
+ }
+}
+
+impl fmt::Display for SystemdId128Error {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ SystemdId128Error::InvalidAppId => f.write_str("Provided application ID is invalid."),
+ SystemdId128Error::GenerationError => {
+ f.write_str("Failed to generate machine-id based on application ID.")
+ }
+ }
+ }
+}
+
+pub fn get_app_specific_id(app_id: [u8; 16]) -> Result<[u8; 16], SystemdId128Error> {
+ let mut res = sd_id128_t { bytes: [0; 16] };
+
+ if app_id.iter().all(|b| *b == 0) {
+ return Err(SystemdId128Error::InvalidAppId);
+ }
+ unsafe {
+ sys::sd_id128_get_machine_app_specific(sd_id128_t { bytes: app_id }, &mut res);
+ }
+ if res.bytes.iter().all(|b| *b == 0) {
+ return Err(SystemdId128Error::GenerationError);
+ }
+ Ok(res.bytes)
+}
+
+#[test]
+fn test_invalid_app_id() {
+ let invalid = [0; 16];
+ let res = get_app_specific_id(invalid);
+ assert!(res.is_err());
+ assert_eq!(res, Err(SystemdId128Error::InvalidAppId));
+}
+
+#[test]
+fn test_valid_app_id() {
+ // no machine-id, no app-specific ID either..
+ if !std::path::Path::new("/etc/machine-id").exists() {
+ return;
+ }
+
+ // UUID generated with `systemd-id128 new` and converted from hex
+ let valid = 950247666410175165299169499632875718_u128.to_le_bytes();
+
+ let res = get_app_specific_id(valid);
+ assert!(res.is_ok());
+
+ let res2 = get_app_specific_id(valid);
+ assert!(res2.is_ok());
+
+ // cannot verify the expected result, since that depends on the machine the test runs on
+ // we can verify that two generations using the same machine and app-id give identical results
+ assert_eq!(res, res2);
+}
diff --git a/proxmox-systemd/src/sys.rs b/proxmox-systemd/src/sys.rs
index eabd44d1..ea2b6061 100644
--- a/proxmox-systemd/src/sys.rs
+++ b/proxmox-systemd/src/sys.rs
@@ -4,6 +4,11 @@ use std::os::fd::RawFd;
pub const LISTEN_FDS_START: RawFd = 3;
+#[repr(C)]
+pub struct sd_id128_t {
+ pub bytes: [u8; 16],
+}
+
#[link(name = "systemd")]
unsafe extern "C" {
pub fn sd_journal_stream_fd(
@@ -24,6 +29,7 @@ unsafe extern "C" {
unset_environment: c_int,
names: *mut *mut *mut c_char,
) -> c_int;
+ pub fn sd_id128_get_machine_app_specific(app_id: sd_id128_t, ret: *mut sd_id128_t) -> c_int;
}
pub fn check_call(ret: c_int) -> Result<c_int, io::Error> {
--
2.47.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH proxmox-backup v2 3/9] api: add /nodes/localhost/identity
2026-04-24 8:29 [PATCH common/proxmox{,-backup}/storage v2 0/9] establish unique instance-id for PBS nodes Lukas Wagner
2026-04-24 8:29 ` [PATCH proxmox v2 1/9] pbs-api-types: add ServerIdentity response type Lukas Wagner
2026-04-24 8:29 ` [PATCH proxmox v2 2/9] systemd: add support for machine-id generation Lukas Wagner
@ 2026-04-24 8:29 ` Lukas Wagner
2026-04-24 8:29 ` [PATCH proxmox-backup v2 4/9] client: add 'server-identity' sub-command Lukas Wagner
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Lukas Wagner @ 2026-04-24 8:29 UTC (permalink / raw)
To: pbs-devel, pve-devel
This one returns a unique ID that can be used to uniquely identify a PBS
node. This will be used by PDM to match PBS storages in a PVE cluster to
PBS remotes in PDM, mainly for associating backup jobs with the
appropriate PBS remote. Later we can also use this to match PBS sync
jobs to their matching PBS remotes in PDM.
The instance ID is derived from /etc/machine-id as recommended by
systemd [1] by using proxmox_systemd::sd_id128::get_app_specific_id.
[1] https://www.freedesktop.org/software/systemd/man/latest/sd_id128_get_machine_app_specific.html
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
src/api2/node/mod.rs | 40 +++++++++++++++++++++++++++++++++++++---
1 file changed, 37 insertions(+), 3 deletions(-)
diff --git a/src/api2/node/mod.rs b/src/api2/node/mod.rs
index 42e1dbaa2..3d48629e1 100644
--- a/src/api2/node/mod.rs
+++ b/src/api2/node/mod.rs
@@ -25,7 +25,7 @@ use proxmox_schema::*;
use proxmox_sortable_macro::sortable;
use proxmox_sys::fd::fd_change_cloexec;
-use pbs_api_types::{NodeShellTicket, NODE_SCHEMA, PRIV_SYS_CONSOLE};
+use pbs_api_types::{NodeShellTicket, ServerIdentity, NODE_SCHEMA, PRIV_SYS_CONSOLE};
use tracing::{info, warn};
use crate::auth::{private_auth_keyring, public_auth_keyring};
@@ -291,12 +291,46 @@ fn list_nodes() -> Result<Value, Error> {
Ok(json!([ { "node": proxmox_sys::nodename().to_string() } ]))
}
-pub const SUBDIRS: SubdirMap = &[
+/// Static key used for deriving a unique instance id from `/etc/machine-id` using
+/// [`proxmox_systemd::sd_id128::get_app_specific_id`].
+///
+/// This key was generated by `systemd-id128 new`.
+///
+const INSTANCE_ID_KEY: [u8; 16] = 0xe5415d9999c146399b8bdae1260e19d2_u128.to_le_bytes();
+
+#[api(
+ input: {
+ properties: {
+ node: {
+ schema: NODE_SCHEMA,
+ optional: true,
+ },
+ }
+ },
+ returns: {
+ type: ServerIdentity,
+ },
+ access: {
+ permission: &Permission::Anybody,
+ }
+)]
+/// Returns a unique server identity. The ID is derived from `/etc/machine-id`.
+pub fn get_identity() -> Result<ServerIdentity, Error> {
+ let machine_id_derived_app_id =
+ proxmox_systemd::sd_id128::get_app_specific_id(INSTANCE_ID_KEY)?;
+ let pbs_instance_id = hex::encode(machine_id_derived_app_id);
+
+ Ok(ServerIdentity { pbs_instance_id })
+}
+
+#[sortable]
+pub const SUBDIRS: SubdirMap = &sorted!([
("apt", &apt::ROUTER),
("certificates", &certificates::ROUTER),
("config", &config::ROUTER),
("disks", &disks::ROUTER),
("dns", &dns::ROUTER),
+ ("identity", &Router::new().get(&API_METHOD_GET_IDENTITY)),
("journal", &journal::ROUTER),
("network", &network::ROUTER),
("report", &report::ROUTER),
@@ -312,7 +346,7 @@ pub const SUBDIRS: SubdirMap = &[
"vncwebsocket",
&Router::new().upgrade(&API_METHOD_WEBSOCKET),
),
-];
+]);
pub const ITEM_ROUTER: Router = Router::new()
.get(&list_subdirs_api_method!(SUBDIRS))
--
2.47.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH proxmox-backup v2 4/9] client: add 'server-identity' sub-command
2026-04-24 8:29 [PATCH common/proxmox{,-backup}/storage v2 0/9] establish unique instance-id for PBS nodes Lukas Wagner
` (2 preceding siblings ...)
2026-04-24 8:29 ` [PATCH proxmox-backup v2 3/9] api: add /nodes/localhost/identity Lukas Wagner
@ 2026-04-24 8:29 ` Lukas Wagner
2026-04-24 8:29 ` [PATCH proxmox-backup v2 5/9] manager: add 'server-identity' subcommand Lukas Wagner
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Lukas Wagner @ 2026-04-24 8:29 UTC (permalink / raw)
To: pbs-devel, pve-devel
This allows users to query the pbs-instance-id from the
proxmox-backup-client tool. This will also be used by the PBS client in
PVE to lookup the pbs-instance-id from a yet to be introduced API
endpoint that returns the pbs-instance-id for a given PBS storage.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
proxmox-backup-client/src/main.rs | 42 +++++++++++++++++++++++++++++--
1 file changed, 40 insertions(+), 2 deletions(-)
diff --git a/proxmox-backup-client/src/main.rs b/proxmox-backup-client/src/main.rs
index 7e63b63c0..1c1ad9a0f 100644
--- a/proxmox-backup-client/src/main.rs
+++ b/proxmox-backup-client/src/main.rs
@@ -26,8 +26,8 @@ use pxar::accessor::{MaybeReady, ReadAt, ReadAtOperation};
use pbs_api_types::{
ArchiveType, Authid, BackupArchiveName, BackupDir, BackupGroup, BackupNamespace, BackupPart,
BackupType, ClientRateLimitConfig, CryptMode, Fingerprint, GroupListItem, PathPattern,
- PruneJobOptions, PruneListItem, RateLimitConfig, SnapshotListItem, StorageStatus,
- BACKUP_ID_SCHEMA, BACKUP_TIME_SCHEMA, BACKUP_TYPE_SCHEMA, CATALOG_NAME,
+ PruneJobOptions, PruneListItem, RateLimitConfig, ServerIdentity, SnapshotListItem,
+ StorageStatus, BACKUP_ID_SCHEMA, BACKUP_TIME_SCHEMA, BACKUP_TYPE_SCHEMA, CATALOG_NAME,
ENCRYPTED_KEY_BLOB_NAME, MANIFEST_BLOB_NAME,
};
use pbs_client::catalog_shell::Shell;
@@ -140,6 +140,40 @@ fn record_repository(repo: &BackupRepository) {
);
}
+#[api(
+ input: {
+ properties: {
+ repo: {
+ type: BackupRepositoryArgs,
+ flatten: true,
+ },
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ },
+ },
+)]
+/// Return the server identity information for this Proxmox Backup Server.
+async fn get_server_identity(param: Value) -> Result<Value, Error> {
+ let repo = extract_repository_from_value(¶m)?;
+ let output_format = get_output_format(¶m);
+ let client = connect(&repo)?;
+
+ let mut result = client
+ .get("api2/json/nodes/localhost/identity", None)
+ .await?;
+
+ let id: ServerIdentity = serde_json::from_value(result["data"].take())?;
+
+ if output_format == "text" {
+ println!("pbs-instance-id: {}", id.pbs_instance_id);
+ } else {
+ format_and_print_result(&id, &output_format);
+ }
+ Ok(Value::Null)
+}
+
async fn api_datastore_list_snapshots(
client: &HttpClient,
store: &str,
@@ -2054,6 +2088,9 @@ fn main() {
let version_cmd_def =
CliCommand::new(&API_METHOD_API_VERSION).completion_cb("repository", complete_repository);
+ let server_identity_cmd_def = CliCommand::new(&API_METHOD_GET_SERVER_IDENTITY)
+ .completion_cb("repository", complete_repository);
+
let change_owner_cmd_def = CliCommand::new(&API_METHOD_CHANGE_BACKUP_OWNER)
.arg_param(&["group", "new-owner"])
.completion_cb("ns", complete_namespace)
@@ -2064,6 +2101,7 @@ fn main() {
let cmd_def = CliCommandMap::new()
.insert("backup", backup_cmd_def)
.insert("garbage-collect", garbage_collect_cmd_def)
+ .insert("server-identity", server_identity_cmd_def)
.insert("list", list_cmd_def)
.insert("login", login_cmd_def)
.insert("logout", logout_cmd_def)
--
2.47.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH proxmox-backup v2 5/9] manager: add 'server-identity' subcommand
2026-04-24 8:29 [PATCH common/proxmox{,-backup}/storage v2 0/9] establish unique instance-id for PBS nodes Lukas Wagner
` (3 preceding siblings ...)
2026-04-24 8:29 ` [PATCH proxmox-backup v2 4/9] client: add 'server-identity' sub-command Lukas Wagner
@ 2026-04-24 8:29 ` Lukas Wagner
2026-04-24 8:29 ` [PATCH common v2 6/9] pbs-client: add support for the 'server-identity' command Lukas Wagner
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Lukas Wagner @ 2026-04-24 8:29 UTC (permalink / raw)
To: pbs-devel, pve-devel
For the sake of completeness also allow to query the server identity
from the proxmox-backup-manager admin tool.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
src/bin/proxmox_backup_manager/node.rs | 30 ++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/src/bin/proxmox_backup_manager/node.rs b/src/bin/proxmox_backup_manager/node.rs
index 4da61690f..249031539 100644
--- a/src/bin/proxmox_backup_manager/node.rs
+++ b/src/bin/proxmox_backup_manager/node.rs
@@ -32,9 +32,39 @@ fn get_node_config(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Valu
Ok(Value::Null)
}
+#[api(
+ input: {
+ properties: {
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ }
+ }
+)]
+/// Return the server identity information for this Proxmox Backup Server.
+fn get_server_identity(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
+ let output_format = get_output_format(¶m);
+
+ let info = &api2::node::API_METHOD_GET_IDENTITY;
+ let mut data = match info.handler {
+ ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
+ _ => unreachable!(),
+ };
+
+ let options = default_table_format_options();
+ format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
+
+ Ok(Value::Null)
+}
+
pub fn node_commands() -> CommandLineInterface {
let cmd_def = CliCommandMap::new()
.insert("show", CliCommand::new(&API_METHOD_GET_NODE_CONFIG))
+ .insert(
+ "server-identity",
+ CliCommand::new(&API_METHOD_GET_SERVER_IDENTITY),
+ )
.insert(
"update",
CliCommand::new(&api2::node::config::API_METHOD_UPDATE_NODE_CONFIG)
--
2.47.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH common v2 6/9] pbs-client: add support for the 'server-identity' command
2026-04-24 8:29 [PATCH common/proxmox{,-backup}/storage v2 0/9] establish unique instance-id for PBS nodes Lukas Wagner
` (4 preceding siblings ...)
2026-04-24 8:29 ` [PATCH proxmox-backup v2 5/9] manager: add 'server-identity' subcommand Lukas Wagner
@ 2026-04-24 8:29 ` Lukas Wagner
2026-04-24 8:29 ` [PATCH pve-storage v2 7/9] plugin: add get_identity method Lukas Wagner
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Lukas Wagner @ 2026-04-24 8:29 UTC (permalink / raw)
To: pbs-devel, pve-devel
This allows us to retrieve a unique instance identifier for a PBS
server.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
src/PVE/PBSClient.pm | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/PVE/PBSClient.pm b/src/PVE/PBSClient.pm
index 6333304..5af0d00 100644
--- a/src/PVE/PBSClient.pm
+++ b/src/PVE/PBSClient.pm
@@ -257,6 +257,13 @@ my sub split_namespaced_parameter : prototype($$) {
return ($namespace, $snapshot);
}
+# Get the server identity information for this backup server.
+sub get_server_identity {
+ my ($self) = @_;
+
+ return run_client_cmd($self, "server-identity");
+}
+
# lists all snapshots, optionally limited to a specific group
sub get_snapshots {
my ($self, $group) = @_;
--
2.47.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH pve-storage v2 7/9] plugin: add get_identity method
2026-04-24 8:29 [PATCH common/proxmox{,-backup}/storage v2 0/9] establish unique instance-id for PBS nodes Lukas Wagner
` (5 preceding siblings ...)
2026-04-24 8:29 ` [PATCH common v2 6/9] pbs-client: add support for the 'server-identity' command Lukas Wagner
@ 2026-04-24 8:29 ` Lukas Wagner
2026-04-24 8:29 ` [PATCH pve-storage v2 8/9] bump storage plugin APIVER and reset APIAGE Lukas Wagner
2026-04-24 8:29 ` [PATCH pve-storage v2 9/9] api: add /nodes/<node>/storage/<storage>/identity route Lukas Wagner
8 siblings, 0 replies; 10+ messages in thread
From: Lukas Wagner @ 2026-04-24 8:29 UTC (permalink / raw)
To: pbs-devel, pve-devel
This one should return a unique identifier for each distinct storage
entity.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
src/PVE/Storage/PBSPlugin.pm | 9 +++++++++
src/PVE/Storage/Plugin.pm | 17 +++++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/src/PVE/Storage/PBSPlugin.pm b/src/PVE/Storage/PBSPlugin.pm
index 17e285a..b916fe4 100644
--- a/src/PVE/Storage/PBSPlugin.pm
+++ b/src/PVE/Storage/PBSPlugin.pm
@@ -1002,4 +1002,13 @@ sub volume_has_feature {
return undef;
}
+sub get_identity {
+ my ($class, $scfg, $storeid) = @_;
+
+ my $client = PVE::PBSClient->new($scfg, $storeid);
+ my $ret = $client->get_server_identity();
+
+ return $ret->{'pbs-instance-id'};
+}
+
1;
diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm
index afd3141..691aad3 100644
--- a/src/PVE/Storage/Plugin.pm
+++ b/src/PVE/Storage/Plugin.pm
@@ -2569,4 +2569,21 @@ sub config_aware_base_mkdir {
}
}
+=pod
+
+=head3 get_identity
+
+ $plugin->get_identity($scfg, $storeid)
+
+Return a unique identifier for this storage instance. The exact format and semantics
+may vary based on the concrete plugin implementation.
+
+=cut
+
+sub get_identity {
+ my ($class, $scfg, $storeid) = @_;
+
+ die("get_identity not implemented for this plugin");
+}
+
1;
--
2.47.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH pve-storage v2 8/9] bump storage plugin APIVER and reset APIAGE
2026-04-24 8:29 [PATCH common/proxmox{,-backup}/storage v2 0/9] establish unique instance-id for PBS nodes Lukas Wagner
` (6 preceding siblings ...)
2026-04-24 8:29 ` [PATCH pve-storage v2 7/9] plugin: add get_identity method Lukas Wagner
@ 2026-04-24 8:29 ` Lukas Wagner
2026-04-24 8:29 ` [PATCH pve-storage v2 9/9] api: add /nodes/<node>/storage/<storage>/identity route Lukas Wagner
8 siblings, 0 replies; 10+ messages in thread
From: Lukas Wagner @ 2026-04-24 8:29 UTC (permalink / raw)
To: pbs-devel, pve-devel
This is done due to the inclusion of the new `get_identity` method.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
src/PVE/Storage.pm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/PVE/Storage.pm b/src/PVE/Storage.pm
index 6e87bac..f7fd60e 100755
--- a/src/PVE/Storage.pm
+++ b/src/PVE/Storage.pm
@@ -41,11 +41,11 @@ use PVE::Storage::BTRFSPlugin;
use PVE::Storage::ESXiPlugin;
# Storage API version. Increment it on changes in storage API interface.
-use constant APIVER => 13;
+use constant APIVER => 14;
# Age is the number of versions we're backward compatible with.
# This is like having 'current=APIVER' and age='APIAGE' in libtool,
# see https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
-use constant APIAGE => 4;
+use constant APIAGE => 0;
our $KNOWN_EXPORT_FORMATS = ['raw+size', 'tar+size', 'qcow2+size', 'vmdk+size', 'zfs', 'btrfs'];
--
2.47.3
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH pve-storage v2 9/9] api: add /nodes/<node>/storage/<storage>/identity route
2026-04-24 8:29 [PATCH common/proxmox{,-backup}/storage v2 0/9] establish unique instance-id for PBS nodes Lukas Wagner
` (7 preceding siblings ...)
2026-04-24 8:29 ` [PATCH pve-storage v2 8/9] bump storage plugin APIVER and reset APIAGE Lukas Wagner
@ 2026-04-24 8:29 ` Lukas Wagner
8 siblings, 0 replies; 10+ messages in thread
From: Lukas Wagner @ 2026-04-24 8:29 UTC (permalink / raw)
To: pbs-devel, pve-devel
This API allows us to retrieve the instance ID of PBS storages. This is
useful to establish a mapping between PBS storage and PBS remotes in
PDM.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
Notes:
Changes since v2:
- Change the return value as proposed by Thomas (include a type
discrimininant and rename pbs-instance-id to id)
- retrieve the identifier through the PBS plugin
Changes since RFC v1:
- Change endpoint path from 'instance-id' to 'identity', as this is
more generic and could make more sense for other storages, if they
ever need such a thing
- Remove unused RpcEnv code
- Adapt PBSClient call to 'get_server_identity'
src/PVE/API2/Storage/Status.pm | 57 +++++++++++++++++++++++++++++++++-
1 file changed, 56 insertions(+), 1 deletion(-)
diff --git a/src/PVE/API2/Storage/Status.pm b/src/PVE/API2/Storage/Status.pm
index 8225c3a..fb921cb 100644
--- a/src/PVE/API2/Storage/Status.pm
+++ b/src/PVE/API2/Storage/Status.pm
@@ -14,7 +14,7 @@ use PVE::JSONSchema qw(get_standard_option);
use PVE::RESTHandler;
use PVE::RPCEnvironment;
use PVE::RRD;
-use PVE::Tools qw(run_command);
+use PVE::Tools qw(run_command extract_param);
use PVE::API2::Storage::Content;
use PVE::API2::Storage::FileRestore;
@@ -23,6 +23,8 @@ use PVE::Storage;
use base qw(PVE::RESTHandler);
+my $storage_type_enum = PVE::Storage::Plugin->lookup_types();
+
__PACKAGE__->register_method({
subclass => "PVE::API2::Storage::PruneBackups",
path => '{storage}/prunebackups',
@@ -308,6 +310,7 @@ __PACKAGE__->register_method({
{ subdir => 'download-url' },
{ subdir => 'file-restore' },
{ subdir => 'import-metadata' },
+ { subdir => 'identity' },
{ subdir => 'oci-registry-pull' },
{ subdir => 'prunebackups' },
{ subdir => 'rrd' },
@@ -1118,4 +1121,56 @@ __PACKAGE__->register_method({
},
});
+__PACKAGE__->register_method({
+ name => 'identity',
+ path => '{storage}/identity',
+ method => 'GET',
+ description => "Return identity information for this storage instance.",
+ permissions => {
+ check => ['perm', '/storage/{storage}', ['Datastore.Audit']],
+ },
+ protected => 1,
+ proxyto => 'node',
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ storage => get_standard_option('pve-storage-id'),
+ },
+ },
+ returns => {
+ type => "object",
+ properties => {
+ 'type' => {
+ type => 'string',
+ description => 'The type of the storage.',
+ enum => $storage_type_enum,
+ },
+ 'id' => {
+ type => 'string',
+ description => 'Unique identifier for this storage instance."
+ . " The exact format and semantics depend on the storage plugin type.',
+ },
+ },
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $storeid = extract_param($param, 'storage');
+
+ my $cfg = PVE::Storage::config();
+ my $scfg = PVE::Storage::storage_config($cfg, $storeid);
+
+ my $type = $scfg->{type};
+ my $plugin = PVE::Storage::Plugin->lookup($type);
+
+ my $id = $plugin->get_identity($scfg, $storeid);
+
+ return {
+ type => $type,
+ id => $id,
+ };
+ },
+});
+
1;
--
2.47.3
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-04-24 8:31 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-04-24 8:29 [PATCH common/proxmox{,-backup}/storage v2 0/9] establish unique instance-id for PBS nodes Lukas Wagner
2026-04-24 8:29 ` [PATCH proxmox v2 1/9] pbs-api-types: add ServerIdentity response type Lukas Wagner
2026-04-24 8:29 ` [PATCH proxmox v2 2/9] systemd: add support for machine-id generation Lukas Wagner
2026-04-24 8:29 ` [PATCH proxmox-backup v2 3/9] api: add /nodes/localhost/identity Lukas Wagner
2026-04-24 8:29 ` [PATCH proxmox-backup v2 4/9] client: add 'server-identity' sub-command Lukas Wagner
2026-04-24 8:29 ` [PATCH proxmox-backup v2 5/9] manager: add 'server-identity' subcommand Lukas Wagner
2026-04-24 8:29 ` [PATCH common v2 6/9] pbs-client: add support for the 'server-identity' command Lukas Wagner
2026-04-24 8:29 ` [PATCH pve-storage v2 7/9] plugin: add get_identity method Lukas Wagner
2026-04-24 8:29 ` [PATCH pve-storage v2 8/9] bump storage plugin APIVER and reset APIAGE Lukas Wagner
2026-04-24 8:29 ` [PATCH pve-storage v2 9/9] api: add /nodes/<node>/storage/<storage>/identity route Lukas Wagner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox