2021-07-07 07:24:39 +00:00
|
|
|
//! Basic API types used by most of the PBS code.
|
|
|
|
|
2021-07-07 12:37:47 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
2021-11-23 16:57:00 +00:00
|
|
|
pub mod common_regex;
|
2021-11-25 10:48:52 +00:00
|
|
|
pub mod percent_encoding;
|
2021-11-23 16:57:00 +00:00
|
|
|
|
2021-10-08 09:19:37 +00:00
|
|
|
use proxmox_schema::{
|
2022-04-10 15:53:42 +00:00
|
|
|
api, const_regex, ApiStringFormat, ApiType, ArraySchema, ReturnType, Schema, StringSchema,
|
2021-10-08 09:19:37 +00:00
|
|
|
};
|
2021-11-17 11:29:31 +00:00
|
|
|
use proxmox_time::parse_daily_duration;
|
2021-07-07 07:04:09 +00:00
|
|
|
|
2021-07-07 09:28:53 +00:00
|
|
|
#[rustfmt::skip]
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! PROXMOX_SAFE_ID_REGEX_STR { () => { r"(?:[A-Za-z0-9_][A-Za-z0-9._\-]*)" }; }
|
|
|
|
|
|
|
|
#[rustfmt::skip]
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! BACKUP_ID_RE { () => (r"[A-Za-z0-9_][A-Za-z0-9._\-]*") }
|
|
|
|
|
|
|
|
#[rustfmt::skip]
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! BACKUP_TYPE_RE { () => (r"(?:host|vm|ct)") }
|
|
|
|
|
|
|
|
#[rustfmt::skip]
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! BACKUP_TIME_RE { () => (r"[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z") }
|
|
|
|
|
api-types: add BackupNamespace type
The idea is to have namespaces in a datastore to allow grouping and
namespacing backups from different (but similar trusted) sources,
e.g., different PVE clusters, geo sites, use-cases or company
service-branches, without separating the underlying
deduplication domain and thus blowing up data and (GC/verify)
resource usage.
To avoid namespace ID clashes with anything existing or future
usecases use a intermediate `ns` level on *each* depth.
The current implementation treats that as internal and thus hides
that fact from the API, iow., the namespace path the users passes
along or gets returned won't include the `ns` level, they do not
matter there at all.
The max-depth of 8 is chosen with the following in mind:
- assume that end-users already are in a deeper level of a hierarchy,
most often they'll start at level one or two, as the higher ones
are used by the seller/admin to namespace different users/groups,
so lower than four would be very limiting for a lot of target use
cases
- all the more, a PBS could be used as huge second level archive in a
big company, so one could imagine a namespace structure like:
/<state>/<intra-state-location>/<datacenter>/<company-branch>/<workload-type>/<service-type>/
e.g.: /us/east-coast/dc12345/financial/report-storage/cassandra/
that's six levels that one can imagine for a reasonable use-case,
leave some room for the ones harder to imagine ;-)
- on the other hand, we do not want to allow unlimited levels as we
have request parameter limits and deep nesting can create other
issues as well (e.g., stack exhaustion), so doubling the minimum
level of 4 (1st point) we got room to breath even for the
more odd (or huge) use cases (2nd point)
- a per-level length of 32 (-1 due to separator) is enough to use
telling names, making lives of users and admin simpler, but not
blowing up parameter total length with the max depth of 8
- 8 * 32 = 256 which is nice buffer size
Much thanks for Wolfgang for all the great work on the type
implementation and assisting greatly with the design.
Co-authored-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Co-authored-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2021-04-07 10:28:50 +00:00
|
|
|
#[rustfmt::skip]
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! BACKUP_NS_RE {
|
|
|
|
() => (
|
2022-04-25 09:52:12 +00:00
|
|
|
concat!(r"(?:", PROXMOX_SAFE_ID_REGEX_STR!(), r"/){0,7}", PROXMOX_SAFE_ID_REGEX_STR!())
|
api-types: add BackupNamespace type
The idea is to have namespaces in a datastore to allow grouping and
namespacing backups from different (but similar trusted) sources,
e.g., different PVE clusters, geo sites, use-cases or company
service-branches, without separating the underlying
deduplication domain and thus blowing up data and (GC/verify)
resource usage.
To avoid namespace ID clashes with anything existing or future
usecases use a intermediate `ns` level on *each* depth.
The current implementation treats that as internal and thus hides
that fact from the API, iow., the namespace path the users passes
along or gets returned won't include the `ns` level, they do not
matter there at all.
The max-depth of 8 is chosen with the following in mind:
- assume that end-users already are in a deeper level of a hierarchy,
most often they'll start at level one or two, as the higher ones
are used by the seller/admin to namespace different users/groups,
so lower than four would be very limiting for a lot of target use
cases
- all the more, a PBS could be used as huge second level archive in a
big company, so one could imagine a namespace structure like:
/<state>/<intra-state-location>/<datacenter>/<company-branch>/<workload-type>/<service-type>/
e.g.: /us/east-coast/dc12345/financial/report-storage/cassandra/
that's six levels that one can imagine for a reasonable use-case,
leave some room for the ones harder to imagine ;-)
- on the other hand, we do not want to allow unlimited levels as we
have request parameter limits and deep nesting can create other
issues as well (e.g., stack exhaustion), so doubling the minimum
level of 4 (1st point) we got room to breath even for the
more odd (or huge) use cases (2nd point)
- a per-level length of 32 (-1 due to separator) is enough to use
telling names, making lives of users and admin simpler, but not
blowing up parameter total length with the max depth of 8
- 8 * 32 = 256 which is nice buffer size
Much thanks for Wolfgang for all the great work on the type
implementation and assisting greatly with the design.
Co-authored-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Co-authored-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2021-04-07 10:28:50 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-07-07 09:28:53 +00:00
|
|
|
#[rustfmt::skip]
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! SNAPSHOT_PATH_REGEX_STR {
|
|
|
|
() => (
|
2022-04-21 13:04:59 +00:00
|
|
|
concat!(
|
|
|
|
r"(", BACKUP_TYPE_RE!(), ")/(", BACKUP_ID_RE!(), ")/(", BACKUP_TIME_RE!(), r")",
|
|
|
|
)
|
2021-07-07 09:28:53 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-25 09:33:12 +00:00
|
|
|
#[rustfmt::skip]
|
2022-04-21 13:04:59 +00:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! GROUP_OR_SNAPSHOT_PATH_REGEX_STR {
|
|
|
|
() => {
|
2022-04-25 09:33:12 +00:00
|
|
|
concat!(
|
|
|
|
r"(", BACKUP_TYPE_RE!(), ")/(", BACKUP_ID_RE!(), ")(?:/(", BACKUP_TIME_RE!(), r"))?",
|
|
|
|
)
|
2022-04-21 13:04:59 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-09-09 08:32:44 +00:00
|
|
|
mod acl;
|
|
|
|
pub use acl::*;
|
|
|
|
|
|
|
|
mod datastore;
|
|
|
|
pub use datastore::*;
|
|
|
|
|
2021-11-19 12:48:38 +00:00
|
|
|
mod human_byte;
|
|
|
|
pub use human_byte::HumanByte;
|
|
|
|
|
2021-09-07 10:32:01 +00:00
|
|
|
mod jobs;
|
|
|
|
pub use jobs::*;
|
|
|
|
|
2021-09-06 08:19:29 +00:00
|
|
|
mod key_derivation;
|
|
|
|
pub use key_derivation::{Kdf, KeyInfo};
|
|
|
|
|
2022-04-12 05:25:56 +00:00
|
|
|
mod maintenance;
|
|
|
|
pub use maintenance::*;
|
|
|
|
|
2021-09-08 10:22:48 +00:00
|
|
|
mod network;
|
|
|
|
pub use network::*;
|
|
|
|
|
2021-07-07 07:53:48 +00:00
|
|
|
#[macro_use]
|
|
|
|
mod userid;
|
|
|
|
pub use userid::Authid;
|
|
|
|
pub use userid::Userid;
|
|
|
|
pub use userid::{Realm, RealmRef};
|
|
|
|
pub use userid::{Tokenname, TokennameRef};
|
|
|
|
pub use userid::{Username, UsernameRef};
|
|
|
|
pub use userid::{PROXMOX_GROUP_ID_SCHEMA, PROXMOX_TOKEN_ID_SCHEMA, PROXMOX_TOKEN_NAME_SCHEMA};
|
|
|
|
|
2021-07-19 08:50:18 +00:00
|
|
|
#[macro_use]
|
|
|
|
mod user;
|
2021-09-09 11:14:28 +00:00
|
|
|
pub use user::*;
|
2021-07-19 08:50:18 +00:00
|
|
|
|
2021-10-08 09:19:37 +00:00
|
|
|
pub use proxmox_schema::upid::*;
|
2021-07-07 11:47:17 +00:00
|
|
|
|
2021-07-09 12:26:42 +00:00
|
|
|
mod crypto;
|
2022-04-10 15:53:42 +00:00
|
|
|
pub use crypto::{bytes_as_fingerprint, CryptMode, Fingerprint};
|
2021-07-09 12:26:42 +00:00
|
|
|
|
2021-08-31 08:45:32 +00:00
|
|
|
pub mod file_restore;
|
|
|
|
|
2021-11-18 10:19:44 +00:00
|
|
|
mod openid;
|
|
|
|
pub use openid::*;
|
|
|
|
|
2021-09-02 12:25:15 +00:00
|
|
|
mod remote;
|
|
|
|
pub use remote::*;
|
|
|
|
|
2021-09-03 07:10:18 +00:00
|
|
|
mod tape;
|
|
|
|
pub use tape::*;
|
|
|
|
|
2021-11-06 17:46:58 +00:00
|
|
|
mod traffic_control;
|
|
|
|
pub use traffic_control::*;
|
|
|
|
|
2021-09-09 08:32:44 +00:00
|
|
|
mod zfs;
|
|
|
|
pub use zfs::*;
|
|
|
|
|
2021-07-09 09:31:53 +00:00
|
|
|
#[rustfmt::skip]
|
|
|
|
#[macro_use]
|
|
|
|
mod local_macros {
|
|
|
|
macro_rules! DNS_LABEL { () => (r"(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)") }
|
|
|
|
macro_rules! DNS_NAME { () => (concat!(r"(?:(?:", DNS_LABEL!() , r"\.)*", DNS_LABEL!(), ")")) }
|
|
|
|
macro_rules! CIDR_V4_REGEX_STR { () => (concat!(r"(?:", IPV4RE!(), r"/\d{1,2})$")) }
|
|
|
|
macro_rules! CIDR_V6_REGEX_STR { () => (concat!(r"(?:", IPV6RE!(), r"/\d{1,3})$")) }
|
|
|
|
macro_rules! DNS_ALIAS_LABEL { () => (r"(?:[a-zA-Z0-9_](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)") }
|
|
|
|
macro_rules! DNS_ALIAS_NAME {
|
|
|
|
() => (concat!(r"(?:(?:", DNS_ALIAS_LABEL!() , r"\.)*", DNS_ALIAS_LABEL!(), ")"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-07 07:04:09 +00:00
|
|
|
const_regex! {
|
2021-07-09 09:31:53 +00:00
|
|
|
pub IP_V4_REGEX = concat!(r"^", IPV4RE!(), r"$");
|
|
|
|
pub IP_V6_REGEX = concat!(r"^", IPV6RE!(), r"$");
|
|
|
|
pub IP_REGEX = concat!(r"^", IPRE!(), r"$");
|
|
|
|
pub CIDR_V4_REGEX = concat!(r"^", CIDR_V4_REGEX_STR!(), r"$");
|
|
|
|
pub CIDR_V6_REGEX = concat!(r"^", CIDR_V6_REGEX_STR!(), r"$");
|
|
|
|
pub CIDR_REGEX = concat!(r"^(?:", CIDR_V4_REGEX_STR!(), "|", CIDR_V6_REGEX_STR!(), r")$");
|
|
|
|
pub HOSTNAME_REGEX = r"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)$";
|
|
|
|
pub DNS_NAME_REGEX = concat!(r"^", DNS_NAME!(), r"$");
|
|
|
|
pub DNS_ALIAS_REGEX = concat!(r"^", DNS_ALIAS_NAME!(), r"$");
|
|
|
|
pub DNS_NAME_OR_IP_REGEX = concat!(r"^(?:", DNS_NAME!(), "|", IPRE!(), r")$");
|
|
|
|
|
|
|
|
pub SHA256_HEX_REGEX = r"^[a-f0-9]{64}$"; // fixme: define in common_regex ?
|
|
|
|
|
|
|
|
pub PASSWORD_REGEX = r"^[[:^cntrl:]]*$"; // everything but control characters
|
|
|
|
|
|
|
|
pub UUID_REGEX = r"^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$";
|
|
|
|
|
2021-09-09 08:32:44 +00:00
|
|
|
pub SYSTEMD_DATETIME_REGEX = r"^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$"; // fixme: define in common_regex ?
|
2021-07-07 09:28:53 +00:00
|
|
|
|
2021-07-07 07:04:09 +00:00
|
|
|
pub FINGERPRINT_SHA256_REGEX = r"^(?:[0-9a-fA-F][0-9a-fA-F])(?::[0-9a-fA-F][0-9a-fA-F]){31}$";
|
2021-07-07 07:49:35 +00:00
|
|
|
|
2022-01-13 09:16:15 +00:00
|
|
|
// just a rough check - dummy acceptor is used before persisting
|
|
|
|
pub OPENSSL_CIPHERS_REGEX = r"^[0-9A-Za-z_:, +!\-@=.]+$";
|
2022-01-11 11:39:35 +00:00
|
|
|
|
2021-07-07 07:49:35 +00:00
|
|
|
/// Regex for safe identifiers.
|
|
|
|
///
|
|
|
|
/// This
|
|
|
|
/// [article](https://dwheeler.com/essays/fixing-unix-linux-filenames.html)
|
|
|
|
/// contains further information why it is reasonable to restict
|
|
|
|
/// names this way. This is not only useful for filenames, but for
|
|
|
|
/// any identifier command line tools work with.
|
|
|
|
pub PROXMOX_SAFE_ID_REGEX = concat!(r"^", PROXMOX_SAFE_ID_REGEX_STR!(), r"$");
|
|
|
|
|
|
|
|
pub SINGLE_LINE_COMMENT_REGEX = r"^[[:^cntrl:]]*$";
|
2021-07-09 09:31:53 +00:00
|
|
|
|
2022-03-04 11:31:57 +00:00
|
|
|
pub MULTI_LINE_COMMENT_REGEX = r"(?m)^([[:^cntrl:]]*)$";
|
|
|
|
|
2021-07-09 09:31:53 +00:00
|
|
|
pub BACKUP_REPO_URL_REGEX = concat!(
|
|
|
|
r"^^(?:(?:(",
|
|
|
|
USER_ID_REGEX_STR!(), "|", APITOKEN_ID_REGEX_STR!(),
|
|
|
|
")@)?(",
|
|
|
|
DNS_NAME!(), "|", IPRE_BRACKET!(),
|
|
|
|
"):)?(?:([0-9]{1,5}):)?(", PROXMOX_SAFE_ID_REGEX_STR!(), r")$"
|
|
|
|
);
|
2021-09-01 12:37:11 +00:00
|
|
|
|
|
|
|
pub BLOCKDEVICE_NAME_REGEX = r"^(:?(:?h|s|x?v)d[a-z]+)|(:?nvme\d+n\d+)$";
|
2021-09-09 08:32:44 +00:00
|
|
|
pub SUBSCRIPTION_KEY_REGEX = concat!(r"^pbs(?:[cbsp])-[0-9a-f]{10}$");
|
2021-07-07 07:04:09 +00:00
|
|
|
}
|
|
|
|
|
2021-07-09 09:31:53 +00:00
|
|
|
pub const IP_V4_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_V4_REGEX);
|
|
|
|
pub const IP_V6_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_V6_REGEX);
|
|
|
|
pub const IP_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_REGEX);
|
|
|
|
pub const CIDR_V4_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_V4_REGEX);
|
|
|
|
pub const CIDR_V6_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_V6_REGEX);
|
|
|
|
pub const CIDR_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_REGEX);
|
2021-09-09 08:32:44 +00:00
|
|
|
pub const PVE_CONFIG_DIGEST_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SHA256_HEX_REGEX);
|
|
|
|
pub const PASSWORD_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&PASSWORD_REGEX);
|
|
|
|
pub const UUID_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&UUID_REGEX);
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const BLOCKDEVICE_NAME_FORMAT: ApiStringFormat =
|
|
|
|
ApiStringFormat::Pattern(&BLOCKDEVICE_NAME_REGEX);
|
|
|
|
pub const SUBSCRIPTION_KEY_FORMAT: ApiStringFormat =
|
|
|
|
ApiStringFormat::Pattern(&SUBSCRIPTION_KEY_REGEX);
|
|
|
|
pub const SYSTEMD_DATETIME_FORMAT: ApiStringFormat =
|
|
|
|
ApiStringFormat::Pattern(&SYSTEMD_DATETIME_REGEX);
|
2021-09-09 08:32:44 +00:00
|
|
|
pub const HOSTNAME_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&HOSTNAME_REGEX);
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const OPENSSL_CIPHERS_TLS_FORMAT: ApiStringFormat =
|
|
|
|
ApiStringFormat::Pattern(&OPENSSL_CIPHERS_REGEX);
|
2021-09-09 08:32:44 +00:00
|
|
|
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const DNS_ALIAS_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&DNS_ALIAS_REGEX);
|
2021-09-09 08:32:44 +00:00
|
|
|
|
2021-11-06 17:46:58 +00:00
|
|
|
pub const DAILY_DURATION_FORMAT: ApiStringFormat =
|
|
|
|
ApiStringFormat::VerifyFn(|s| parse_daily_duration(s).map(drop));
|
|
|
|
|
2021-09-09 08:32:44 +00:00
|
|
|
pub const SEARCH_DOMAIN_SCHEMA: Schema =
|
|
|
|
StringSchema::new("Search domain for host-name lookup.").schema();
|
|
|
|
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const FIRST_DNS_SERVER_SCHEMA: Schema = StringSchema::new("First name server IP address.")
|
2021-09-09 08:32:44 +00:00
|
|
|
.format(&IP_FORMAT)
|
|
|
|
.schema();
|
|
|
|
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const SECOND_DNS_SERVER_SCHEMA: Schema = StringSchema::new("Second name server IP address.")
|
2021-09-09 08:32:44 +00:00
|
|
|
.format(&IP_FORMAT)
|
|
|
|
.schema();
|
|
|
|
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const THIRD_DNS_SERVER_SCHEMA: Schema = StringSchema::new("Third name server IP address.")
|
2021-09-09 08:32:44 +00:00
|
|
|
.format(&IP_FORMAT)
|
|
|
|
.schema();
|
|
|
|
|
|
|
|
pub const HOSTNAME_SCHEMA: Schema = StringSchema::new("Hostname (as defined in RFC1123).")
|
|
|
|
.format(&HOSTNAME_FORMAT)
|
|
|
|
.schema();
|
2021-07-09 09:31:53 +00:00
|
|
|
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const OPENSSL_CIPHERS_TLS_1_2_SCHEMA: Schema =
|
|
|
|
StringSchema::new("OpenSSL cipher list used by the proxy for TLS <= 1.2")
|
|
|
|
.format(&OPENSSL_CIPHERS_TLS_FORMAT)
|
|
|
|
.schema();
|
2022-01-11 11:39:35 +00:00
|
|
|
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const OPENSSL_CIPHERS_TLS_1_3_SCHEMA: Schema =
|
|
|
|
StringSchema::new("OpenSSL ciphersuites list used by the proxy for TLS 1.3")
|
|
|
|
.format(&OPENSSL_CIPHERS_TLS_FORMAT)
|
|
|
|
.schema();
|
2022-01-11 11:39:35 +00:00
|
|
|
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const DNS_NAME_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&DNS_NAME_REGEX);
|
2021-09-02 12:25:15 +00:00
|
|
|
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const DNS_NAME_OR_IP_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&DNS_NAME_OR_IP_REGEX);
|
2021-09-02 12:25:15 +00:00
|
|
|
|
|
|
|
pub const DNS_NAME_OR_IP_SCHEMA: Schema = StringSchema::new("DNS name or IP address.")
|
|
|
|
.format(&DNS_NAME_OR_IP_FORMAT)
|
|
|
|
.schema();
|
|
|
|
|
2021-09-09 08:32:44 +00:00
|
|
|
pub const NODE_SCHEMA: Schema = StringSchema::new("Node name (or 'localhost')")
|
2022-01-12 13:52:10 +00:00
|
|
|
.format(&HOSTNAME_FORMAT)
|
2021-07-09 12:26:42 +00:00
|
|
|
.schema();
|
2021-09-09 08:32:44 +00:00
|
|
|
|
|
|
|
pub const TIME_ZONE_SCHEMA: Schema = StringSchema::new(
|
2022-04-10 15:53:42 +00:00
|
|
|
"Time zone. The file '/usr/share/zoneinfo/zone.tab' contains the list of valid names.",
|
|
|
|
)
|
|
|
|
.format(&SINGLE_LINE_COMMENT_FORMAT)
|
|
|
|
.min_length(2)
|
|
|
|
.max_length(64)
|
|
|
|
.schema();
|
2021-07-09 12:26:42 +00:00
|
|
|
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const BLOCKDEVICE_NAME_SCHEMA: Schema =
|
|
|
|
StringSchema::new("Block device name (/sys/block/<name>).")
|
|
|
|
.format(&BLOCKDEVICE_NAME_FORMAT)
|
|
|
|
.min_length(3)
|
|
|
|
.max_length(64)
|
|
|
|
.schema();
|
2021-09-09 08:32:44 +00:00
|
|
|
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const DISK_ARRAY_SCHEMA: Schema =
|
|
|
|
ArraySchema::new("Disk name list.", &BLOCKDEVICE_NAME_SCHEMA).schema();
|
2021-09-09 08:32:44 +00:00
|
|
|
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const DISK_LIST_SCHEMA: Schema = StringSchema::new("A list of disk names, comma separated.")
|
2021-09-09 08:32:44 +00:00
|
|
|
.format(&ApiStringFormat::PropertyString(&DISK_ARRAY_SCHEMA))
|
|
|
|
.schema();
|
|
|
|
|
|
|
|
pub const PASSWORD_SCHEMA: Schema = StringSchema::new("Password.")
|
|
|
|
.format(&PASSWORD_FORMAT)
|
|
|
|
.min_length(1)
|
|
|
|
.max_length(1024)
|
|
|
|
.schema();
|
|
|
|
|
|
|
|
pub const PBS_PASSWORD_SCHEMA: Schema = StringSchema::new("User Password.")
|
|
|
|
.format(&PASSWORD_FORMAT)
|
|
|
|
.min_length(5)
|
|
|
|
.max_length(64)
|
2021-07-09 12:26:42 +00:00
|
|
|
.schema();
|
|
|
|
|
2021-09-02 10:47:11 +00:00
|
|
|
pub const REALM_ID_SCHEMA: Schema = StringSchema::new("Realm name.")
|
|
|
|
.format(&PROXMOX_SAFE_ID_FORMAT)
|
|
|
|
.min_length(2)
|
|
|
|
.max_length(32)
|
|
|
|
.schema();
|
|
|
|
|
2021-07-07 07:04:09 +00:00
|
|
|
pub const FINGERPRINT_SHA256_FORMAT: ApiStringFormat =
|
|
|
|
ApiStringFormat::Pattern(&FINGERPRINT_SHA256_REGEX);
|
|
|
|
|
|
|
|
pub const CERT_FINGERPRINT_SHA256_SCHEMA: Schema =
|
|
|
|
StringSchema::new("X509 certificate fingerprint (sha256).")
|
|
|
|
.format(&FINGERPRINT_SHA256_FORMAT)
|
|
|
|
.schema();
|
2021-07-07 07:49:35 +00:00
|
|
|
|
|
|
|
pub const PROXMOX_SAFE_ID_FORMAT: ApiStringFormat =
|
|
|
|
ApiStringFormat::Pattern(&PROXMOX_SAFE_ID_REGEX);
|
|
|
|
|
|
|
|
pub const SINGLE_LINE_COMMENT_FORMAT: ApiStringFormat =
|
|
|
|
ApiStringFormat::Pattern(&SINGLE_LINE_COMMENT_REGEX);
|
|
|
|
|
|
|
|
pub const SINGLE_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (single line).")
|
|
|
|
.format(&SINGLE_LINE_COMMENT_FORMAT)
|
|
|
|
.schema();
|
2022-03-04 11:31:57 +00:00
|
|
|
|
|
|
|
pub const MULTI_LINE_COMMENT_FORMAT: ApiStringFormat =
|
|
|
|
ApiStringFormat::Pattern(&MULTI_LINE_COMMENT_REGEX);
|
|
|
|
|
|
|
|
pub const MULTI_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (multiple lines).")
|
|
|
|
.format(&MULTI_LINE_COMMENT_FORMAT)
|
|
|
|
.schema();
|
2021-07-07 09:28:53 +00:00
|
|
|
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const SUBSCRIPTION_KEY_SCHEMA: Schema =
|
|
|
|
StringSchema::new("Proxmox Backup Server subscription key.")
|
|
|
|
.format(&SUBSCRIPTION_KEY_FORMAT)
|
|
|
|
.min_length(15)
|
|
|
|
.max_length(16)
|
|
|
|
.schema();
|
2021-09-09 08:32:44 +00:00
|
|
|
|
2022-04-10 15:53:42 +00:00
|
|
|
pub const SERVICE_ID_SCHEMA: Schema = StringSchema::new("Service ID.").max_length(256).schema();
|
2021-09-09 08:32:44 +00:00
|
|
|
|
2021-07-19 08:50:18 +00:00
|
|
|
pub const PROXMOX_CONFIG_DIGEST_SCHEMA: Schema = StringSchema::new(
|
|
|
|
"Prevent changes if current configuration file has different \
|
|
|
|
SHA256 digest. This can be used to prevent concurrent \
|
|
|
|
modifications.",
|
|
|
|
)
|
|
|
|
.format(&PVE_CONFIG_DIGEST_FORMAT)
|
|
|
|
.schema();
|
|
|
|
|
2021-07-09 09:31:53 +00:00
|
|
|
/// API schema format definition for repository URLs
|
|
|
|
pub const BACKUP_REPO_URL: ApiStringFormat = ApiStringFormat::Pattern(&BACKUP_REPO_URL_REGEX);
|
|
|
|
|
2021-07-09 12:26:42 +00:00
|
|
|
// Complex type definitions
|
|
|
|
|
2021-07-19 12:59:51 +00:00
|
|
|
#[api()]
|
|
|
|
#[derive(Default, Serialize, Deserialize)]
|
|
|
|
/// Storage space usage information.
|
|
|
|
pub struct StorageStatus {
|
|
|
|
/// Total space (bytes).
|
|
|
|
pub total: u64,
|
|
|
|
/// Used space (bytes).
|
|
|
|
pub used: u64,
|
|
|
|
/// Available space (bytes).
|
|
|
|
pub avail: u64,
|
|
|
|
}
|
|
|
|
|
2021-07-21 12:12:22 +00:00
|
|
|
pub const PASSWORD_HINT_SCHEMA: Schema = StringSchema::new("Password hint.")
|
|
|
|
.format(&SINGLE_LINE_COMMENT_FORMAT)
|
|
|
|
.min_length(1)
|
|
|
|
.max_length(64)
|
|
|
|
.schema();
|
|
|
|
|
2021-09-07 10:32:01 +00:00
|
|
|
#[api()]
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
#[serde(rename_all = "PascalCase")]
|
|
|
|
/// Describes a package for which an update is available.
|
|
|
|
pub struct APTUpdateInfo {
|
|
|
|
/// Package name
|
|
|
|
pub package: String,
|
|
|
|
/// Package title
|
|
|
|
pub title: String,
|
|
|
|
/// Package architecture
|
|
|
|
pub arch: String,
|
|
|
|
/// Human readable package description
|
|
|
|
pub description: String,
|
|
|
|
/// New version to be updated to
|
|
|
|
pub version: String,
|
|
|
|
/// Old version currently installed
|
|
|
|
pub old_version: String,
|
|
|
|
/// Package origin
|
|
|
|
pub origin: String,
|
|
|
|
/// Package priority in human-readable form
|
|
|
|
pub priority: String,
|
|
|
|
/// Package section
|
|
|
|
pub section: String,
|
|
|
|
/// URL under which the package's changelog can be retrieved
|
|
|
|
pub change_log_url: String,
|
|
|
|
/// Custom extra field for additional package information
|
2022-04-10 15:53:42 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2021-09-07 10:32:01 +00:00
|
|
|
pub extra_info: Option<String>,
|
|
|
|
}
|
2021-09-09 08:32:44 +00:00
|
|
|
|
|
|
|
#[api()]
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
|
|
|
#[serde(rename_all = "lowercase")]
|
|
|
|
/// Node Power command type.
|
|
|
|
pub enum NodePowerCommand {
|
|
|
|
/// Restart the server
|
|
|
|
Reboot,
|
|
|
|
/// Shutdown the server
|
|
|
|
Shutdown,
|
|
|
|
}
|
2021-09-22 10:46:44 +00:00
|
|
|
|
|
|
|
#[api()]
|
|
|
|
#[derive(Eq, PartialEq, Debug, Serialize, Deserialize)]
|
|
|
|
#[serde(rename_all = "lowercase")]
|
|
|
|
pub enum TaskStateType {
|
|
|
|
/// Ok
|
|
|
|
OK,
|
|
|
|
/// Warning
|
|
|
|
Warning,
|
|
|
|
/// Error
|
|
|
|
Error,
|
|
|
|
/// Unknown
|
|
|
|
Unknown,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[api(
|
|
|
|
properties: {
|
|
|
|
upid: { schema: UPID::API_SCHEMA },
|
|
|
|
},
|
|
|
|
)]
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
/// Task properties.
|
|
|
|
pub struct TaskListItem {
|
|
|
|
pub upid: String,
|
|
|
|
/// The node name where the task is running on.
|
|
|
|
pub node: String,
|
|
|
|
/// The Unix PID
|
|
|
|
pub pid: i64,
|
|
|
|
/// The task start time (Epoch)
|
|
|
|
pub pstart: u64,
|
|
|
|
/// The task start time (Epoch)
|
|
|
|
pub starttime: i64,
|
|
|
|
/// Worker type (arbitrary ASCII string)
|
|
|
|
pub worker_type: String,
|
|
|
|
/// Worker ID (arbitrary ASCII string)
|
|
|
|
pub worker_id: Option<String>,
|
|
|
|
/// The authenticated entity who started the task
|
|
|
|
pub user: String,
|
|
|
|
/// The task end time (Epoch)
|
2022-04-10 15:53:42 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2021-09-22 10:46:44 +00:00
|
|
|
pub endtime: Option<i64>,
|
|
|
|
/// Task end status
|
2022-04-10 15:53:42 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2021-09-22 10:46:44 +00:00
|
|
|
pub status: Option<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub const NODE_TASKS_LIST_TASKS_RETURN_TYPE: ReturnType = ReturnType {
|
|
|
|
optional: false,
|
2022-04-10 15:53:42 +00:00
|
|
|
schema: &ArraySchema::new("A list of tasks.", &TaskListItem::API_SCHEMA).schema(),
|
2021-09-22 10:46:44 +00:00
|
|
|
};
|
2021-10-06 07:49:51 +00:00
|
|
|
|
2021-10-13 08:24:44 +00:00
|
|
|
#[api()]
|
|
|
|
#[derive(Copy, Clone, Serialize, Deserialize)]
|
|
|
|
#[serde(rename_all = "UPPERCASE")]
|
|
|
|
/// RRD consolidation mode
|
|
|
|
pub enum RRDMode {
|
|
|
|
/// Maximum
|
|
|
|
Max,
|
|
|
|
/// Average
|
|
|
|
Average,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[api()]
|
|
|
|
#[derive(Copy, Clone, Serialize, Deserialize)]
|
|
|
|
#[serde(rename_all = "lowercase")]
|
|
|
|
/// RRD time frame
|
|
|
|
pub enum RRDTimeFrame {
|
|
|
|
/// Hour
|
|
|
|
Hour,
|
|
|
|
/// Day
|
|
|
|
Day,
|
|
|
|
/// Week
|
|
|
|
Week,
|
|
|
|
/// Month
|
|
|
|
Month,
|
|
|
|
/// Year
|
|
|
|
Year,
|
|
|
|
/// Decade (10 years)
|
|
|
|
Decade,
|
|
|
|
}
|
2022-03-07 06:41:03 +00:00
|
|
|
|
|
|
|
#[api]
|
|
|
|
#[derive(Deserialize, Serialize, PartialEq, Eq)]
|
|
|
|
#[serde(rename_all = "lowercase")]
|
|
|
|
/// type of the realm
|
|
|
|
pub enum RealmType {
|
|
|
|
/// The PAM realm
|
|
|
|
Pam,
|
|
|
|
/// The PBS realm
|
|
|
|
Pbs,
|
|
|
|
/// An OpenID Connect realm
|
|
|
|
OpenId,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[api(
|
|
|
|
properties: {
|
|
|
|
realm: {
|
|
|
|
schema: REALM_ID_SCHEMA,
|
|
|
|
},
|
|
|
|
"type": {
|
|
|
|
type: RealmType,
|
|
|
|
},
|
|
|
|
comment: {
|
|
|
|
optional: true,
|
|
|
|
schema: SINGLE_LINE_COMMENT_SCHEMA,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)]
|
|
|
|
#[derive(Deserialize, Serialize)]
|
|
|
|
#[serde(rename_all = "kebab-case")]
|
|
|
|
/// Basic Information about a realm
|
|
|
|
pub struct BasicRealmInfo {
|
|
|
|
pub realm: String,
|
|
|
|
#[serde(rename = "type")]
|
|
|
|
pub ty: RealmType,
|
|
|
|
/// True if it is the default realm
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
pub default: Option<bool>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
pub comment: Option<String>,
|
|
|
|
}
|