1 use serde
::{Deserialize, Serialize}
;
6 Userid
, Authid
, REMOTE_ID_SCHEMA
, DRIVE_NAME_SCHEMA
, MEDIA_POOL_NAME_SCHEMA
,
7 SINGLE_LINE_COMMENT_SCHEMA
, PROXMOX_SAFE_ID_FORMAT
, DATASTORE_SCHEMA
,
12 /// Regex for verification jobs 'DATASTORE:ACTUAL_JOB_ID'
13 pub VERIFICATION_JOB_WORKER_ID_REGEX
= concat
!(r
"^(", PROXMOX_SAFE_ID_REGEX_STR
!(), r
"):");
14 /// Regex for sync jobs 'REMOTE:REMOTE_DATASTORE:LOCAL_DATASTORE:ACTUAL_JOB_ID'
15 pub SYNC_JOB_WORKER_ID_REGEX
= concat
!(r
"^(", PROXMOX_SAFE_ID_REGEX_STR
!(), r
"):(", PROXMOX_SAFE_ID_REGEX_STR
!(), r
"):(", PROXMOX_SAFE_ID_REGEX_STR
!(), r
"):");
18 pub const JOB_ID_SCHEMA
: Schema
= StringSchema
::new("Job ID.")
19 .format(&PROXMOX_SAFE_ID_FORMAT
)
24 pub const SYNC_SCHEDULE_SCHEMA
: Schema
= StringSchema
::new(
25 "Run sync job at specified schedule.")
26 .format(&ApiStringFormat
::VerifyFn(proxmox_systemd
::time
::verify_calendar_event
))
27 .type_text("<calendar-event>")
30 pub const GC_SCHEDULE_SCHEMA
: Schema
= StringSchema
::new(
31 "Run garbage collection job at specified schedule.")
32 .format(&ApiStringFormat
::VerifyFn(proxmox_systemd
::time
::verify_calendar_event
))
33 .type_text("<calendar-event>")
36 pub const PRUNE_SCHEDULE_SCHEMA
: Schema
= StringSchema
::new(
37 "Run prune job at specified schedule.")
38 .format(&ApiStringFormat
::VerifyFn(proxmox_systemd
::time
::verify_calendar_event
))
39 .type_text("<calendar-event>")
42 pub const VERIFICATION_SCHEDULE_SCHEMA
: Schema
= StringSchema
::new(
43 "Run verify job at specified schedule.")
44 .format(&ApiStringFormat
::VerifyFn(proxmox_systemd
::time
::verify_calendar_event
))
45 .type_text("<calendar-event>")
48 pub const REMOVE_VANISHED_BACKUPS_SCHEMA
: Schema
= BooleanSchema
::new(
49 "Delete vanished backups. This remove the local copy if the remote backup was deleted.")
56 description
: "Estimated time of the next run (UNIX epoch).",
61 description
: "Result of the last run.",
66 description
: "Task UPID of the last run.",
71 description
: "Endtime of the last run.",
77 #[derive(Serialize,Deserialize,Default)]
78 #[serde(rename_all="kebab-case")]
79 /// Job Scheduling Status
80 pub struct JobScheduleStatus
{
81 #[serde(skip_serializing_if="Option::is_none")]
82 pub next_run
: Option
<i64>,
83 #[serde(skip_serializing_if="Option::is_none")]
84 pub last_run_state
: Option
<String
>,
85 #[serde(skip_serializing_if="Option::is_none")]
86 pub last_run_upid
: Option
<String
>,
87 #[serde(skip_serializing_if="Option::is_none")]
88 pub last_run_endtime
: Option
<i64>,
92 #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
93 #[serde(rename_all = "lowercase")]
94 /// When do we send notifications
96 /// Never send notification
98 /// Send notifications for failed and successful jobs
100 /// Send notifications for failed jobs only
120 #[derive(Debug, Serialize, Deserialize)]
121 /// Datastore notify settings
122 pub struct DatastoreNotify
{
123 /// Garbage collection settings
124 pub gc
: Option
<Notify
>,
125 /// Verify job setting
126 pub verify
: Option
<Notify
>,
128 pub sync
: Option
<Notify
>,
131 pub const DATASTORE_NOTIFY_STRING_SCHEMA
: Schema
= StringSchema
::new(
132 "Datastore notification setting")
133 .format(&ApiStringFormat
::PropertyString(&DatastoreNotify
::API_SCHEMA
))
136 pub const IGNORE_VERIFIED_BACKUPS_SCHEMA
: Schema
= BooleanSchema
::new(
137 "Do not verify backups that are already verified if their verification is not outdated.")
141 pub const VERIFICATION_OUTDATED_AFTER_SCHEMA
: Schema
= IntegerSchema
::new(
142 "Days after that a verification becomes outdated")
149 schema
: JOB_ID_SCHEMA
,
152 schema
: DATASTORE_SCHEMA
,
156 schema
: IGNORE_VERIFIED_BACKUPS_SCHEMA
,
160 schema
: VERIFICATION_OUTDATED_AFTER_SCHEMA
,
164 schema
: SINGLE_LINE_COMMENT_SCHEMA
,
168 schema
: VERIFICATION_SCHEDULE_SCHEMA
,
172 #[derive(Serialize,Deserialize,Updater)]
173 #[serde(rename_all="kebab-case")]
175 pub struct VerificationJobConfig
{
176 /// unique ID to address this job
179 /// the datastore ID this verificaiton job affects
181 #[serde(skip_serializing_if="Option::is_none")]
182 /// if not set to false, check the age of the last snapshot verification to filter
183 /// out recent ones, depending on 'outdated_after' configuration.
184 pub ignore_verified
: Option
<bool
>,
185 #[serde(skip_serializing_if="Option::is_none")]
186 /// Reverify snapshots after X days, never if 0. Ignored if 'ignore_verified' is false.
187 pub outdated_after
: Option
<i64>,
188 #[serde(skip_serializing_if="Option::is_none")]
189 pub comment
: Option
<String
>,
190 #[serde(skip_serializing_if="Option::is_none")]
191 /// when to schedule this job in calendar event notation
192 pub schedule
: Option
<String
>,
198 type: VerificationJobConfig
,
201 type: JobScheduleStatus
,
205 #[derive(Serialize,Deserialize)]
206 #[serde(rename_all="kebab-case")]
207 /// Status of Verification Job
208 pub struct VerificationJobStatus
{
210 pub config
: VerificationJobConfig
,
212 pub status
: JobScheduleStatus
,
218 schema
: DATASTORE_SCHEMA
,
221 schema
: MEDIA_POOL_NAME_SCHEMA
,
224 schema
: DRIVE_NAME_SCHEMA
,
227 description
: "Eject media upon job completion.",
231 "export-media-set": {
232 description
: "Export media set upon job completion.",
237 description
: "Backup latest snapshots only.",
247 #[derive(Serialize,Deserialize,Clone,Updater)]
248 #[serde(rename_all="kebab-case")]
249 /// Tape Backup Job Setup
250 pub struct TapeBackupJobSetup
{
254 #[serde(skip_serializing_if="Option::is_none")]
255 pub eject_media
: Option
<bool
>,
256 #[serde(skip_serializing_if="Option::is_none")]
257 pub export_media_set
: Option
<bool
>,
258 #[serde(skip_serializing_if="Option::is_none")]
259 pub latest_only
: Option
<bool
>,
260 /// Send job email notification to this user
261 #[serde(skip_serializing_if="Option::is_none")]
262 pub notify_user
: Option
<Userid
>,
268 schema
: JOB_ID_SCHEMA
,
271 type: TapeBackupJobSetup
,
275 schema
: SINGLE_LINE_COMMENT_SCHEMA
,
279 schema
: SYNC_SCHEDULE_SCHEMA
,
283 #[derive(Serialize,Deserialize,Clone,Updater)]
284 #[serde(rename_all="kebab-case")]
286 pub struct TapeBackupJobConfig
{
290 pub setup
: TapeBackupJobSetup
,
291 #[serde(skip_serializing_if="Option::is_none")]
292 pub comment
: Option
<String
>,
293 #[serde(skip_serializing_if="Option::is_none")]
294 pub schedule
: Option
<String
>,
300 type: TapeBackupJobConfig
,
303 type: JobScheduleStatus
,
307 #[derive(Serialize,Deserialize)]
308 #[serde(rename_all="kebab-case")]
309 /// Status of Tape Backup Job
310 pub struct TapeBackupJobStatus
{
312 pub config
: TapeBackupJobConfig
,
314 pub status
: JobScheduleStatus
,
315 /// Next tape used (best guess)
316 #[serde(skip_serializing_if="Option::is_none")]
317 pub next_media_label
: Option
<String
>,
323 schema
: JOB_ID_SCHEMA
,
326 schema
: DATASTORE_SCHEMA
,
333 schema
: REMOTE_ID_SCHEMA
,
336 schema
: DATASTORE_SCHEMA
,
339 schema
: REMOVE_VANISHED_BACKUPS_SCHEMA
,
344 schema
: SINGLE_LINE_COMMENT_SCHEMA
,
348 schema
: SYNC_SCHEDULE_SCHEMA
,
352 #[derive(Serialize,Deserialize,Clone,Updater)]
353 #[serde(rename_all="kebab-case")]
355 pub struct SyncJobConfig
{
359 #[serde(skip_serializing_if="Option::is_none")]
360 pub owner
: Option
<Authid
>,
362 pub remote_store
: String
,
363 #[serde(skip_serializing_if="Option::is_none")]
364 pub remove_vanished
: Option
<bool
>,
365 #[serde(skip_serializing_if="Option::is_none")]
366 pub comment
: Option
<String
>,
367 #[serde(skip_serializing_if="Option::is_none")]
368 pub schedule
: Option
<String
>,
377 type: JobScheduleStatus
,
382 #[derive(Serialize,Deserialize)]
383 #[serde(rename_all="kebab-case")]
384 /// Status of Sync Job
385 pub struct SyncJobStatus
{
387 pub config
: SyncJobConfig
,
389 pub status
: JobScheduleStatus
,