2 use ::serde
::{Deserialize, Serialize}
;
4 use proxmox
::api
::{api, const_regex, schema::*}
;
5 use proxmox
::tools
::*; // required to use IPRE!() macro ???
7 // File names: may not contain slashes, may not start with "."
8 pub const FILENAME_FORMAT
: ApiStringFormat
= ApiStringFormat
::VerifyFn(|name
| {
9 if name
.starts_with('
.'
) {
10 bail
!("file names may not start with '.'");
12 if name
.contains('
/'
) {
13 bail
!("file names may not contain slashes");
18 macro_rules
! DNS_LABEL { () => (r"(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)") }
19 macro_rules
! DNS_NAME { () => (concat!(r"(?:", DNS_LABEL!() , r"\.)*", DNS_LABEL!())) }
21 // we only allow a limited set of characters
22 // colon is not allowed, because we store usernames in
23 // colon separated lists)!
24 // slash is not allowed because it is used as pve API delimiter
25 // also see "man useradd"
26 macro_rules
! USER_NAME_REGEX_STR { () => (r"(?:[^\s:/[:cntrl:]]+)") }
28 macro_rules
! PROXMOX_SAFE_ID_REGEX_STR { () => (r"(?:[A-Za-z0-9_][A-Za-z0-9._\-]*)") }
31 pub IP_FORMAT_REGEX
= IPRE
!();
32 pub SHA256_HEX_REGEX
= r
"^[a-f0-9]{64}$"; // fixme: define in common_regex ?
33 pub SYSTEMD_DATETIME_REGEX
= r
"^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$"; // fixme: define in common_regex ?
35 /// Regex for safe identifiers.
38 /// [article](https://dwheeler.com/essays/fixing-unix-linux-filenames.html)
39 /// contains further information why it is reasonable to restict
40 /// names this way. This is not only useful for filenames, but for
41 /// any identifier command line tools work with.
42 pub PROXMOX_SAFE_ID_REGEX
= concat
!(r
"^", PROXMOX_SAFE_ID_REGEX_STR
!(), r
"$");
44 pub SINGLE_LINE_COMMENT_REGEX
= r
"^[[:^cntrl:]]*$";
46 pub HOSTNAME_REGEX
= r
"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)$";
48 pub DNS_NAME_REGEX
= concat
!(r
"^", DNS_NAME
!(), r
"$");
50 pub DNS_NAME_OR_IP_REGEX
= concat
!(r
"^", DNS_NAME
!(), "|", IPRE
!(), r
"$");
52 pub PROXMOX_USER_ID_REGEX
= concat
!(r
"^", USER_NAME_REGEX_STR
!(), r
"@", PROXMOX_SAFE_ID_REGEX_STR
!(), r
"$");
55 pub const SYSTEMD_DATETIME_FORMAT
: ApiStringFormat
=
56 ApiStringFormat
::Pattern(&SYSTEMD_DATETIME_REGEX
);
58 pub const IP_FORMAT
: ApiStringFormat
=
59 ApiStringFormat
::Pattern(&IP_FORMAT_REGEX
);
61 pub const PVE_CONFIG_DIGEST_FORMAT
: ApiStringFormat
=
62 ApiStringFormat
::Pattern(&SHA256_HEX_REGEX
);
64 pub const PROXMOX_SAFE_ID_FORMAT
: ApiStringFormat
=
65 ApiStringFormat
::Pattern(&PROXMOX_SAFE_ID_REGEX
);
67 pub const SINGLE_LINE_COMMENT_FORMAT
: ApiStringFormat
=
68 ApiStringFormat
::Pattern(&SINGLE_LINE_COMMENT_REGEX
);
70 pub const HOSTNAME_FORMAT
: ApiStringFormat
=
71 ApiStringFormat
::Pattern(&HOSTNAME_REGEX
);
73 pub const DNS_NAME_FORMAT
: ApiStringFormat
=
74 ApiStringFormat
::Pattern(&DNS_NAME_REGEX
);
76 pub const DNS_NAME_OR_IP_FORMAT
: ApiStringFormat
=
77 ApiStringFormat
::Pattern(&DNS_NAME_OR_IP_REGEX
);
79 pub const PROXMOX_USER_ID_FORMAT
: ApiStringFormat
=
80 ApiStringFormat
::Pattern(&PROXMOX_USER_ID_REGEX
);
83 pub const PVE_CONFIG_DIGEST_SCHEMA
: Schema
= StringSchema
::new(r
#"\
84 Prevent changes if current configuration file has different SHA256 digest.
85 This can be used to prevent concurrent modifications.
88 .format(&PVE_CONFIG_DIGEST_FORMAT
)
92 pub const CHUNK_DIGEST_FORMAT
: ApiStringFormat
=
93 ApiStringFormat
::Pattern(&SHA256_HEX_REGEX
);
95 pub const CHUNK_DIGEST_SCHEMA
: Schema
= StringSchema
::new("Chunk digest (SHA256).")
96 .format(&CHUNK_DIGEST_FORMAT
)
99 pub const NODE_SCHEMA
: Schema
= StringSchema
::new("Node name (or 'localhost')")
100 .format(&ApiStringFormat
::VerifyFn(|node
| {
101 if node
== "localhost" || node
== proxmox
::tools
::nodename() {
104 bail
!("no such node '{}'", node
);
109 pub const SEARCH_DOMAIN_SCHEMA
: Schema
=
110 StringSchema
::new("Search domain for host-name lookup.").schema();
112 pub const FIRST_DNS_SERVER_SCHEMA
: Schema
=
113 StringSchema
::new("First name server IP address.")
117 pub const SECOND_DNS_SERVER_SCHEMA
: Schema
=
118 StringSchema
::new("Second name server IP address.")
122 pub const THIRD_DNS_SERVER_SCHEMA
: Schema
=
123 StringSchema
::new("Third name server IP address.")
127 pub const BACKUP_ARCHIVE_NAME_SCHEMA
: Schema
=
128 StringSchema
::new("Backup archive name.")
129 .format(&PROXMOX_SAFE_ID_FORMAT
)
132 pub const BACKUP_TYPE_SCHEMA
: Schema
=
133 StringSchema
::new("Backup type.")
134 .format(&ApiStringFormat
::Enum(&["vm", "ct", "host"]))
137 pub const BACKUP_ID_SCHEMA
: Schema
=
138 StringSchema
::new("Backup ID.")
139 .format(&PROXMOX_SAFE_ID_FORMAT
)
142 pub const BACKUP_TIME_SCHEMA
: Schema
=
143 IntegerSchema
::new("Backup time (Unix epoch.)")
144 .minimum(1_547_797_308)
147 pub const UPID_SCHEMA
: Schema
= StringSchema
::new("Unique Process/Task ID.")
151 pub const DATASTORE_SCHEMA
: Schema
= StringSchema
::new("Datastore name.")
152 .format(&PROXMOX_SAFE_ID_FORMAT
)
157 pub const REMOTE_ID_SCHEMA
: Schema
= StringSchema
::new("Remote ID.")
158 .format(&PROXMOX_SAFE_ID_FORMAT
)
163 pub const SINGLE_LINE_COMMENT_SCHEMA
: Schema
= StringSchema
::new("Comment (single line).")
164 .format(&SINGLE_LINE_COMMENT_FORMAT
)
167 pub const HOSTNAME_SCHEMA
: Schema
= StringSchema
::new("Hostname (as defined in RFC1123).")
168 .format(&HOSTNAME_FORMAT
)
171 pub const DNS_NAME_OR_IP_SCHEMA
: Schema
= StringSchema
::new("DNS name or IP address.")
172 .format(&DNS_NAME_OR_IP_FORMAT
)
175 pub const PROXMOX_AUTH_REALM_SCHEMA
: Schema
= StringSchema
::new("Authentication domain ID")
176 .format(&PROXMOX_SAFE_ID_FORMAT
)
181 pub const PROXMOX_USER_ID_SCHEMA
: Schema
= StringSchema
::new("User ID")
182 .format(&PROXMOX_USER_ID_FORMAT
)
188 // Complex type definitions
193 schema
: BACKUP_TYPE_SCHEMA
,
196 schema
: BACKUP_ID_SCHEMA
,
199 schema
: BACKUP_TIME_SCHEMA
,
203 schema
: BACKUP_ARCHIVE_NAME_SCHEMA
208 #[derive(Serialize, Deserialize)]
209 #[serde(rename_all="kebab-case")]
210 /// Basic information about backup snapshot.
211 pub struct SnapshotListItem
{
212 pub backup_type
: String
, // enum
213 pub backup_id
: String
,
214 pub backup_time
: i64,
215 /// List of contained archive files.
216 pub files
: Vec
<String
>,
217 /// Overall snapshot size (sum of all archive sizes).
218 #[serde(skip_serializing_if="Option::is_none")]
219 pub size
: Option
<u64>,