]> git.proxmox.com Git - proxmox-backup.git/blame - pbs-api-types/src/lib.rs
move drive config to pbs_config workspace
[proxmox-backup.git] / pbs-api-types / src / lib.rs
CommitLineData
155f657f
WB
1//! Basic API types used by most of the PBS code.
2
c23192d3
WB
3use serde::{Deserialize, Serialize};
4
5use proxmox::api::api;
7b570c17
WB
6use proxmox::api::schema::{
7 ApiStringFormat, ApiType, ArraySchema, EnumEntry, IntegerSchema, ReturnType, Schema,
8 StringSchema,
9};
86fb3877 10use proxmox::const_regex;
75f83c6a 11use proxmox::{IPRE, IPRE_BRACKET, IPV4OCTET, IPV4RE, IPV6H16, IPV6LS32, IPV6RE};
86fb3877 12
bfff4eaa
WB
13#[rustfmt::skip]
14#[macro_export]
15macro_rules! PROXMOX_SAFE_ID_REGEX_STR { () => { r"(?:[A-Za-z0-9_][A-Za-z0-9._\-]*)" }; }
16
17#[rustfmt::skip]
18#[macro_export]
19macro_rules! BACKUP_ID_RE { () => (r"[A-Za-z0-9_][A-Za-z0-9._\-]*") }
20
21#[rustfmt::skip]
22#[macro_export]
23macro_rules! BACKUP_TYPE_RE { () => (r"(?:host|vm|ct)") }
24
25#[rustfmt::skip]
26#[macro_export]
27macro_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") }
28
29#[rustfmt::skip]
30#[macro_export]
31macro_rules! SNAPSHOT_PATH_REGEX_STR {
32 () => (
33 concat!(r"(", BACKUP_TYPE_RE!(), ")/(", BACKUP_ID_RE!(), ")/(", BACKUP_TIME_RE!(), r")")
34 );
35}
36
751f6b61
WB
37#[macro_use]
38mod userid;
39pub use userid::Authid;
40pub use userid::Userid;
41pub use userid::{Realm, RealmRef};
42pub use userid::{Tokenname, TokennameRef};
43pub use userid::{Username, UsernameRef};
44pub use userid::{PROXMOX_GROUP_ID_SCHEMA, PROXMOX_TOKEN_ID_SCHEMA, PROXMOX_TOKEN_NAME_SCHEMA};
45
2b7f8dd5
WB
46#[macro_use]
47mod user;
48pub use user::{ApiToken, User, UserWithTokens};
49pub use user::{
50 EMAIL_SCHEMA, ENABLE_USER_SCHEMA, EXPIRE_USER_SCHEMA, FIRST_NAME_SCHEMA, LAST_NAME_SCHEMA,
51};
52
95f9d67c 53pub mod upid;
c23192d3 54pub use upid::UPID;
95f9d67c 55
ea584a75
WB
56mod crypto;
57pub use crypto::{CryptMode, Fingerprint};
58
013b1e8b
WB
59pub mod file_restore;
60
6afdda88
DM
61mod remote;
62pub use remote::*;
63
1ce8e905
DM
64mod tape;
65pub use tape::*;
66
75f83c6a
WB
67#[rustfmt::skip]
68#[macro_use]
69mod local_macros {
70 macro_rules! DNS_LABEL { () => (r"(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)") }
71 macro_rules! DNS_NAME { () => (concat!(r"(?:(?:", DNS_LABEL!() , r"\.)*", DNS_LABEL!(), ")")) }
72 macro_rules! CIDR_V4_REGEX_STR { () => (concat!(r"(?:", IPV4RE!(), r"/\d{1,2})$")) }
73 macro_rules! CIDR_V6_REGEX_STR { () => (concat!(r"(?:", IPV6RE!(), r"/\d{1,3})$")) }
74 macro_rules! DNS_ALIAS_LABEL { () => (r"(?:[a-zA-Z0-9_](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)") }
75 macro_rules! DNS_ALIAS_NAME {
76 () => (concat!(r"(?:(?:", DNS_ALIAS_LABEL!() , r"\.)*", DNS_ALIAS_LABEL!(), ")"))
77 }
78}
79
86fb3877 80const_regex! {
75f83c6a
WB
81 pub IP_V4_REGEX = concat!(r"^", IPV4RE!(), r"$");
82 pub IP_V6_REGEX = concat!(r"^", IPV6RE!(), r"$");
83 pub IP_REGEX = concat!(r"^", IPRE!(), r"$");
84 pub CIDR_V4_REGEX = concat!(r"^", CIDR_V4_REGEX_STR!(), r"$");
85 pub CIDR_V6_REGEX = concat!(r"^", CIDR_V6_REGEX_STR!(), r"$");
86 pub CIDR_REGEX = concat!(r"^(?:", CIDR_V4_REGEX_STR!(), "|", CIDR_V6_REGEX_STR!(), r")$");
87 pub HOSTNAME_REGEX = r"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)$";
88 pub DNS_NAME_REGEX = concat!(r"^", DNS_NAME!(), r"$");
89 pub DNS_ALIAS_REGEX = concat!(r"^", DNS_ALIAS_NAME!(), r"$");
90 pub DNS_NAME_OR_IP_REGEX = concat!(r"^(?:", DNS_NAME!(), "|", IPRE!(), r")$");
91
92 pub SHA256_HEX_REGEX = r"^[a-f0-9]{64}$"; // fixme: define in common_regex ?
93
94 pub PASSWORD_REGEX = r"^[[:^cntrl:]]*$"; // everything but control characters
95
96 pub UUID_REGEX = r"^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$";
97
bfff4eaa
WB
98 pub BACKUP_TYPE_REGEX = concat!(r"^(", BACKUP_TYPE_RE!(), r")$");
99
100 pub BACKUP_ID_REGEX = concat!(r"^", BACKUP_ID_RE!(), r"$");
101
102 pub BACKUP_DATE_REGEX = concat!(r"^", BACKUP_TIME_RE!() ,r"$");
103
104 pub GROUP_PATH_REGEX = concat!(r"^(", BACKUP_TYPE_RE!(), ")/(", BACKUP_ID_RE!(), r")$");
105
106 pub BACKUP_FILE_REGEX = r"^.*\.([fd]idx|blob)$";
107
108 pub SNAPSHOT_PATH_REGEX = concat!(r"^", SNAPSHOT_PATH_REGEX_STR!(), r"$");
109
86fb3877 110 pub FINGERPRINT_SHA256_REGEX = r"^(?:[0-9a-fA-F][0-9a-fA-F])(?::[0-9a-fA-F][0-9a-fA-F]){31}$";
3c430e9a
WB
111
112 /// Regex for safe identifiers.
113 ///
114 /// This
115 /// [article](https://dwheeler.com/essays/fixing-unix-linux-filenames.html)
116 /// contains further information why it is reasonable to restict
117 /// names this way. This is not only useful for filenames, but for
118 /// any identifier command line tools work with.
119 pub PROXMOX_SAFE_ID_REGEX = concat!(r"^", PROXMOX_SAFE_ID_REGEX_STR!(), r"$");
120
121 pub SINGLE_LINE_COMMENT_REGEX = r"^[[:^cntrl:]]*$";
75f83c6a
WB
122
123 pub BACKUP_REPO_URL_REGEX = concat!(
124 r"^^(?:(?:(",
125 USER_ID_REGEX_STR!(), "|", APITOKEN_ID_REGEX_STR!(),
126 ")@)?(",
127 DNS_NAME!(), "|", IPRE_BRACKET!(),
128 "):)?(?:([0-9]{1,5}):)?(", PROXMOX_SAFE_ID_REGEX_STR!(), r")$"
129 );
4c1b7761
WB
130
131 pub BLOCKDEVICE_NAME_REGEX = r"^(:?(:?h|s|x?v)d[a-z]+)|(:?nvme\d+n\d+)$";
86fb3877
WB
132}
133
75f83c6a
WB
134pub const IP_V4_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_V4_REGEX);
135pub const IP_V6_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_V6_REGEX);
136pub const IP_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_REGEX);
137pub const CIDR_V4_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_V4_REGEX);
138pub const CIDR_V6_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_V6_REGEX);
139pub const CIDR_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_REGEX);
140
6afdda88
DM
141pub const DNS_NAME_FORMAT: ApiStringFormat =
142 ApiStringFormat::Pattern(&DNS_NAME_REGEX);
143
144pub const DNS_NAME_OR_IP_FORMAT: ApiStringFormat =
145 ApiStringFormat::Pattern(&DNS_NAME_OR_IP_REGEX);
146
147pub const DNS_NAME_OR_IP_SCHEMA: Schema = StringSchema::new("DNS name or IP address.")
148 .format(&DNS_NAME_OR_IP_FORMAT)
149 .schema();
150
ea584a75
WB
151pub const BACKUP_ID_SCHEMA: Schema = StringSchema::new("Backup ID.")
152 .format(&BACKUP_ID_FORMAT)
153 .schema();
154pub const BACKUP_TYPE_SCHEMA: Schema = StringSchema::new("Backup type.")
155 .format(&ApiStringFormat::Enum(&[
156 EnumEntry::new("vm", "Virtual Machine Backup"),
157 EnumEntry::new("ct", "Container Backup"),
158 EnumEntry::new("host", "Host Backup"),
159 ]))
160 .schema();
161pub const BACKUP_TIME_SCHEMA: Schema = IntegerSchema::new("Backup time (Unix epoch.)")
162 .minimum(1_547_797_308)
163 .schema();
164
165pub const DATASTORE_SCHEMA: Schema = StringSchema::new("Datastore name.")
166 .format(&PROXMOX_SAFE_ID_FORMAT)
167 .min_length(3)
168 .max_length(32)
169 .schema();
170
21211748
DM
171pub const REALM_ID_SCHEMA: Schema = StringSchema::new("Realm name.")
172 .format(&PROXMOX_SAFE_ID_FORMAT)
173 .min_length(2)
174 .max_length(32)
175 .schema();
176
86fb3877
WB
177pub const FINGERPRINT_SHA256_FORMAT: ApiStringFormat =
178 ApiStringFormat::Pattern(&FINGERPRINT_SHA256_REGEX);
179
180pub const CERT_FINGERPRINT_SHA256_SCHEMA: Schema =
181 StringSchema::new("X509 certificate fingerprint (sha256).")
182 .format(&FINGERPRINT_SHA256_FORMAT)
183 .schema();
3c430e9a 184
2b7f8dd5 185pub const PRUNE_SCHEMA_KEEP_DAILY: Schema = IntegerSchema::new("Number of daily backups to keep.")
ced69458
DC
186 .minimum(1)
187 .schema();
188
2b7f8dd5
WB
189pub const PRUNE_SCHEMA_KEEP_HOURLY: Schema =
190 IntegerSchema::new("Number of hourly backups to keep.")
191 .minimum(1)
192 .schema();
ced69458 193
2b7f8dd5 194pub const PRUNE_SCHEMA_KEEP_LAST: Schema = IntegerSchema::new("Number of backups to keep.")
ced69458
DC
195 .minimum(1)
196 .schema();
197
2b7f8dd5
WB
198pub const PRUNE_SCHEMA_KEEP_MONTHLY: Schema =
199 IntegerSchema::new("Number of monthly backups to keep.")
200 .minimum(1)
201 .schema();
ced69458 202
2b7f8dd5
WB
203pub const PRUNE_SCHEMA_KEEP_WEEKLY: Schema =
204 IntegerSchema::new("Number of weekly backups to keep.")
205 .minimum(1)
206 .schema();
ced69458 207
2b7f8dd5
WB
208pub const PRUNE_SCHEMA_KEEP_YEARLY: Schema =
209 IntegerSchema::new("Number of yearly backups to keep.")
210 .minimum(1)
211 .schema();
ced69458 212
3c430e9a
WB
213pub const PROXMOX_SAFE_ID_FORMAT: ApiStringFormat =
214 ApiStringFormat::Pattern(&PROXMOX_SAFE_ID_REGEX);
215
216pub const SINGLE_LINE_COMMENT_FORMAT: ApiStringFormat =
217 ApiStringFormat::Pattern(&SINGLE_LINE_COMMENT_REGEX);
218
219pub const SINGLE_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (single line).")
220 .format(&SINGLE_LINE_COMMENT_FORMAT)
221 .schema();
bfff4eaa 222
2b7f8dd5
WB
223pub const PROXMOX_CONFIG_DIGEST_SCHEMA: Schema = StringSchema::new(
224 "Prevent changes if current configuration file has different \
225 SHA256 digest. This can be used to prevent concurrent \
226 modifications.",
227)
228.format(&PVE_CONFIG_DIGEST_FORMAT)
229.schema();
230
bfff4eaa 231pub const BACKUP_ID_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&BACKUP_ID_REGEX);
c23192d3 232
75f83c6a
WB
233/// API schema format definition for repository URLs
234pub const BACKUP_REPO_URL: ApiStringFormat = ApiStringFormat::Pattern(&BACKUP_REPO_URL_REGEX);
235
c23192d3
WB
236#[api(
237 properties: {
238 "upid": {
239 optional: true,
240 type: UPID,
241 },
242 },
243)]
244#[derive(Clone, Serialize, Deserialize)]
245#[serde(rename_all = "kebab-case")]
246/// Garbage collection status.
247pub struct GarbageCollectionStatus {
248 pub upid: Option<String>,
249 /// Number of processed index files.
250 pub index_file_count: usize,
251 /// Sum of bytes referred by index files.
252 pub index_data_bytes: u64,
253 /// Bytes used on disk.
254 pub disk_bytes: u64,
255 /// Chunks used on disk.
256 pub disk_chunks: usize,
257 /// Sum of removed bytes.
258 pub removed_bytes: u64,
259 /// Number of removed chunks.
260 pub removed_chunks: usize,
261 /// Sum of pending bytes (pending removal - kept for safety).
262 pub pending_bytes: u64,
263 /// Number of pending chunks (pending removal - kept for safety).
264 pub pending_chunks: usize,
265 /// Number of chunks marked as .bad by verify that have been removed by GC.
266 pub removed_bad: usize,
267 /// Number of chunks still marked as .bad after garbage collection.
268 pub still_bad: usize,
269}
270
271impl Default for GarbageCollectionStatus {
272 fn default() -> Self {
273 GarbageCollectionStatus {
274 upid: None,
275 index_file_count: 0,
276 index_data_bytes: 0,
277 disk_bytes: 0,
278 disk_chunks: 0,
279 removed_bytes: 0,
280 removed_chunks: 0,
281 pending_bytes: 0,
282 pending_chunks: 0,
283 removed_bad: 0,
284 still_bad: 0,
285 }
286 }
287}
75f83c6a
WB
288
289pub const PVE_CONFIG_DIGEST_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SHA256_HEX_REGEX);
290pub const CHUNK_DIGEST_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SHA256_HEX_REGEX);
291
292pub const PASSWORD_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&PASSWORD_REGEX);
293
294pub const UUID_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&UUID_REGEX);
ea584a75
WB
295
296pub const BACKUP_ARCHIVE_NAME_SCHEMA: Schema = StringSchema::new("Backup archive name.")
297 .format(&PROXMOX_SAFE_ID_FORMAT)
298 .schema();
299
300// Complex type definitions
301
302#[api(
303 properties: {
304 "filename": {
305 schema: BACKUP_ARCHIVE_NAME_SCHEMA,
306 },
307 "crypt-mode": {
308 type: CryptMode,
309 optional: true,
310 },
311 },
312)]
313#[derive(Serialize, Deserialize)]
314#[serde(rename_all = "kebab-case")]
315/// Basic information about archive files inside a backup snapshot.
316pub struct BackupContent {
317 pub filename: String,
318 /// Info if file is encrypted, signed, or neither.
319 #[serde(skip_serializing_if = "Option::is_none")]
320 pub crypt_mode: Option<CryptMode>,
321 /// Archive size (from backup manifest).
322 #[serde(skip_serializing_if = "Option::is_none")]
323 pub size: Option<u64>,
324}
325
326#[api()]
327#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
328#[serde(rename_all = "lowercase")]
329/// Result of a verify operation.
330pub enum VerifyState {
331 /// Verification was successful
332 Ok,
333 /// Verification reported one or more errors
334 Failed,
335}
336
337#[api(
338 properties: {
339 upid: {
340 type: UPID,
341 },
342 state: {
343 type: VerifyState,
344 },
345 },
346)]
347#[derive(Serialize, Deserialize)]
348/// Task properties.
349pub struct SnapshotVerifyState {
350 /// UPID of the verify task
351 pub upid: UPID,
352 /// State of the verification. Enum.
353 pub state: VerifyState,
354}
355
356#[api(
357 properties: {
358 "backup-type": {
359 schema: BACKUP_TYPE_SCHEMA,
360 },
361 "backup-id": {
362 schema: BACKUP_ID_SCHEMA,
363 },
364 "backup-time": {
365 schema: BACKUP_TIME_SCHEMA,
366 },
367 comment: {
368 schema: SINGLE_LINE_COMMENT_SCHEMA,
369 optional: true,
370 },
371 verification: {
372 type: SnapshotVerifyState,
373 optional: true,
374 },
375 fingerprint: {
376 type: String,
377 optional: true,
378 },
379 files: {
380 items: {
381 schema: BACKUP_ARCHIVE_NAME_SCHEMA
382 },
383 },
384 owner: {
385 type: Authid,
386 optional: true,
387 },
388 },
389)]
390#[derive(Serialize, Deserialize)]
391#[serde(rename_all = "kebab-case")]
392/// Basic information about backup snapshot.
393pub struct SnapshotListItem {
394 pub backup_type: String, // enum
395 pub backup_id: String,
396 pub backup_time: i64,
397 /// The first line from manifest "notes"
398 #[serde(skip_serializing_if = "Option::is_none")]
399 pub comment: Option<String>,
400 /// The result of the last run verify task
401 #[serde(skip_serializing_if = "Option::is_none")]
402 pub verification: Option<SnapshotVerifyState>,
403 /// Fingerprint of encryption key
404 #[serde(skip_serializing_if = "Option::is_none")]
405 pub fingerprint: Option<Fingerprint>,
406 /// List of contained archive files.
407 pub files: Vec<BackupContent>,
408 /// Overall snapshot size (sum of all archive sizes).
409 #[serde(skip_serializing_if = "Option::is_none")]
410 pub size: Option<u64>,
411 /// The owner of the snapshots group
412 #[serde(skip_serializing_if = "Option::is_none")]
413 pub owner: Option<Authid>,
414}
415
416#[api(
417 properties: {
418 "backup-type": {
419 schema: BACKUP_TYPE_SCHEMA,
420 },
421 "backup-id": {
422 schema: BACKUP_ID_SCHEMA,
423 },
424 "last-backup": {
425 schema: BACKUP_TIME_SCHEMA,
426 },
427 "backup-count": {
428 type: Integer,
429 },
430 files: {
431 items: {
432 schema: BACKUP_ARCHIVE_NAME_SCHEMA
433 },
434 },
435 owner: {
436 type: Authid,
437 optional: true,
438 },
439 },
440)]
441#[derive(Serialize, Deserialize)]
442#[serde(rename_all = "kebab-case")]
443/// Basic information about a backup group.
444pub struct GroupListItem {
445 pub backup_type: String, // enum
446 pub backup_id: String,
447 pub last_backup: i64,
448 /// Number of contained snapshots
449 pub backup_count: u64,
450 /// List of contained archive files.
451 pub files: Vec<String>,
452 /// The owner of group
453 #[serde(skip_serializing_if = "Option::is_none")]
454 pub owner: Option<Authid>,
d6688884 455 /// The first line from group "notes"
2b7f8dd5 456 #[serde(skip_serializing_if = "Option::is_none")]
d6688884 457 pub comment: Option<String>,
ea584a75
WB
458}
459
460#[api(
461 properties: {
462 store: {
463 schema: DATASTORE_SCHEMA,
464 },
465 comment: {
466 optional: true,
467 schema: SINGLE_LINE_COMMENT_SCHEMA,
468 },
469 },
470)]
471#[derive(Serialize, Deserialize)]
472#[serde(rename_all = "kebab-case")]
473/// Basic information about a datastore.
474pub struct DataStoreListItem {
475 pub store: String,
476 pub comment: Option<String>,
477}
478
479#[api(
480 properties: {
481 "backup-type": {
482 schema: BACKUP_TYPE_SCHEMA,
483 },
484 "backup-id": {
485 schema: BACKUP_ID_SCHEMA,
486 },
487 "backup-time": {
488 schema: BACKUP_TIME_SCHEMA,
489 },
490 },
491)]
492#[derive(Serialize, Deserialize)]
493#[serde(rename_all = "kebab-case")]
494/// Prune result.
495pub struct PruneListItem {
496 pub backup_type: String, // enum
497 pub backup_id: String,
498 pub backup_time: i64,
499 /// Keep snapshot
500 pub keep: bool,
501}
51ec8a3c
WB
502
503#[api()]
504#[derive(Default, Serialize, Deserialize)]
505/// Storage space usage information.
506pub struct StorageStatus {
507 /// Total space (bytes).
508 pub total: u64,
509 /// Used space (bytes).
510 pub used: u64,
511 /// Available space (bytes).
512 pub avail: u64,
513}
514
515#[api()]
516#[derive(Serialize, Deserialize, Default)]
517/// Backup Type group/snapshot counts.
518pub struct TypeCounts {
519 /// The number of groups of the type.
520 pub groups: u64,
521 /// The number of snapshots of the type.
522 pub snapshots: u64,
523}
524
525#[api(
526 properties: {
527 ct: {
528 type: TypeCounts,
529 optional: true,
530 },
531 host: {
532 type: TypeCounts,
533 optional: true,
534 },
535 vm: {
536 type: TypeCounts,
537 optional: true,
538 },
539 other: {
540 type: TypeCounts,
541 optional: true,
542 },
543 },
544)]
545#[derive(Serialize, Deserialize, Default)]
546/// Counts of groups/snapshots per BackupType.
547pub struct Counts {
548 /// The counts for CT backups
549 pub ct: Option<TypeCounts>,
550 /// The counts for Host backups
551 pub host: Option<TypeCounts>,
552 /// The counts for VM backups
553 pub vm: Option<TypeCounts>,
554 /// The counts for other backup types
555 pub other: Option<TypeCounts>,
556}
eb5e0ae6
WB
557
558pub const PASSWORD_HINT_SCHEMA: Schema = StringSchema::new("Password hint.")
559 .format(&SINGLE_LINE_COMMENT_FORMAT)
560 .min_length(1)
561 .max_length(64)
562 .schema();
563
564
565#[api]
566#[derive(Deserialize, Serialize)]
567/// RSA public key information
568pub struct RsaPubKeyInfo {
569 /// Path to key (if stored in a file)
570 #[serde(skip_serializing_if="Option::is_none")]
571 pub path: Option<String>,
572 /// RSA exponent
573 pub exponent: String,
574 /// Hex-encoded RSA modulus
575 pub modulus: String,
576 /// Key (modulus) length in bits
577 pub length: usize,
578}
579
580impl std::convert::TryFrom<openssl::rsa::Rsa<openssl::pkey::Public>> for RsaPubKeyInfo {
581 type Error = anyhow::Error;
582
583 fn try_from(value: openssl::rsa::Rsa<openssl::pkey::Public>) -> Result<Self, Self::Error> {
584 let modulus = value.n().to_hex_str()?.to_string();
585 let exponent = value.e().to_dec_str()?.to_string();
586 let length = value.size() as usize * 8;
587
588 Ok(Self {
589 path: None,
590 exponent,
591 modulus,
592 length,
593 })
594 }
595}
7b570c17
WB
596
597#[api(
598 properties: {
599 upid: { schema: UPID::API_SCHEMA },
600 },
601)]
602#[derive(Serialize, Deserialize)]
603/// Task properties.
604pub struct TaskListItem {
605 pub upid: String,
606 /// The node name where the task is running on.
607 pub node: String,
608 /// The Unix PID
609 pub pid: i64,
610 /// The task start time (Epoch)
611 pub pstart: u64,
612 /// The task start time (Epoch)
613 pub starttime: i64,
614 /// Worker type (arbitrary ASCII string)
615 pub worker_type: String,
616 /// Worker ID (arbitrary ASCII string)
617 pub worker_id: Option<String>,
618 /// The authenticated entity who started the task
619 pub user: Authid,
620 /// The task end time (Epoch)
621 #[serde(skip_serializing_if="Option::is_none")]
622 pub endtime: Option<i64>,
623 /// Task end status
624 #[serde(skip_serializing_if="Option::is_none")]
625 pub status: Option<String>,
626}
627
628pub const ADMIN_DATASTORE_LIST_SNAPSHOTS_RETURN_TYPE: ReturnType = ReturnType {
629 optional: false,
630 schema: &ArraySchema::new(
631 "Returns the list of snapshots.",
632 &SnapshotListItem::API_SCHEMA,
633 ).schema(),
634};
635
636pub const ADMIN_DATASTORE_LIST_SNAPSHOT_FILES_RETURN_TYPE: ReturnType = ReturnType {
637 optional: false,
638 schema: &ArraySchema::new(
639 "Returns the list of archive files inside a backup snapshots.",
640 &BackupContent::API_SCHEMA,
641 ).schema(),
642};
643
644pub const ADMIN_DATASTORE_LIST_GROUPS_RETURN_TYPE: ReturnType = ReturnType {
645 optional: false,
646 schema: &ArraySchema::new(
647 "Returns the list of backup groups.",
648 &GroupListItem::API_SCHEMA,
649 ).schema(),
650};
651
652pub const ADMIN_DATASTORE_PRUNE_RETURN_TYPE: ReturnType = ReturnType {
653 optional: false,
654 schema: &ArraySchema::new(
655 "Returns the list of snapshots and a flag indicating if there are kept or removed.",
656 &PruneListItem::API_SCHEMA,
657 ).schema(),
658};
659
660pub const NODE_TASKS_LIST_TASKS_RETURN_TYPE: ReturnType = ReturnType {
661 optional: false,
662 schema: &ArraySchema::new(
663 "A list of tasks.",
664 &TaskListItem::API_SCHEMA,
665 ).schema(),
666};