]> git.proxmox.com Git - proxmox-backup.git/blob - pbs-api-types/src/jobs.rs
update to first proxmox crate split
[proxmox-backup.git] / pbs-api-types / src / jobs.rs
1 use serde::{Deserialize, Serialize};
2
3 use proxmox_schema::*;
4
5 use crate::{
6 Userid, Authid, REMOTE_ID_SCHEMA, DRIVE_NAME_SCHEMA, MEDIA_POOL_NAME_SCHEMA,
7 SINGLE_LINE_COMMENT_SCHEMA, PROXMOX_SAFE_ID_FORMAT, DATASTORE_SCHEMA,
8 };
9
10 const_regex!{
11
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"):");
16 }
17
18 pub const JOB_ID_SCHEMA: Schema = StringSchema::new("Job ID.")
19 .format(&PROXMOX_SAFE_ID_FORMAT)
20 .min_length(3)
21 .max_length(32)
22 .schema();
23
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>")
28 .schema();
29
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>")
34 .schema();
35
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>")
40 .schema();
41
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>")
46 .schema();
47
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.")
50 .default(true)
51 .schema();
52
53 #[api(
54 properties: {
55 "next-run": {
56 description: "Estimated time of the next run (UNIX epoch).",
57 optional: true,
58 type: Integer,
59 },
60 "last-run-state": {
61 description: "Result of the last run.",
62 optional: true,
63 type: String,
64 },
65 "last-run-upid": {
66 description: "Task UPID of the last run.",
67 optional: true,
68 type: String,
69 },
70 "last-run-endtime": {
71 description: "Endtime of the last run.",
72 optional: true,
73 type: Integer,
74 },
75 }
76 )]
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>,
89 }
90
91 #[api()]
92 #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
93 #[serde(rename_all = "lowercase")]
94 /// When do we send notifications
95 pub enum Notify {
96 /// Never send notification
97 Never,
98 /// Send notifications for failed and successful jobs
99 Always,
100 /// Send notifications for failed jobs only
101 Error,
102 }
103
104 #[api(
105 properties: {
106 gc: {
107 type: Notify,
108 optional: true,
109 },
110 verify: {
111 type: Notify,
112 optional: true,
113 },
114 sync: {
115 type: Notify,
116 optional: true,
117 },
118 },
119 )]
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>,
127 /// Sync job setting
128 pub sync: Option<Notify>,
129 }
130
131 pub const DATASTORE_NOTIFY_STRING_SCHEMA: Schema = StringSchema::new(
132 "Datastore notification setting")
133 .format(&ApiStringFormat::PropertyString(&DatastoreNotify::API_SCHEMA))
134 .schema();
135
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.")
138 .default(true)
139 .schema();
140
141 pub const VERIFICATION_OUTDATED_AFTER_SCHEMA: Schema = IntegerSchema::new(
142 "Days after that a verification becomes outdated")
143 .minimum(1)
144 .schema();
145
146 #[api(
147 properties: {
148 id: {
149 schema: JOB_ID_SCHEMA,
150 },
151 store: {
152 schema: DATASTORE_SCHEMA,
153 },
154 "ignore-verified": {
155 optional: true,
156 schema: IGNORE_VERIFIED_BACKUPS_SCHEMA,
157 },
158 "outdated-after": {
159 optional: true,
160 schema: VERIFICATION_OUTDATED_AFTER_SCHEMA,
161 },
162 comment: {
163 optional: true,
164 schema: SINGLE_LINE_COMMENT_SCHEMA,
165 },
166 schedule: {
167 optional: true,
168 schema: VERIFICATION_SCHEDULE_SCHEMA,
169 },
170 }
171 )]
172 #[derive(Serialize,Deserialize,Updater)]
173 #[serde(rename_all="kebab-case")]
174 /// Verification Job
175 pub struct VerificationJobConfig {
176 /// unique ID to address this job
177 #[updater(skip)]
178 pub id: String,
179 /// the datastore ID this verificaiton job affects
180 pub store: String,
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>,
193 }
194
195 #[api(
196 properties: {
197 config: {
198 type: VerificationJobConfig,
199 },
200 status: {
201 type: JobScheduleStatus,
202 },
203 },
204 )]
205 #[derive(Serialize,Deserialize)]
206 #[serde(rename_all="kebab-case")]
207 /// Status of Verification Job
208 pub struct VerificationJobStatus {
209 #[serde(flatten)]
210 pub config: VerificationJobConfig,
211 #[serde(flatten)]
212 pub status: JobScheduleStatus,
213 }
214
215 #[api(
216 properties: {
217 store: {
218 schema: DATASTORE_SCHEMA,
219 },
220 pool: {
221 schema: MEDIA_POOL_NAME_SCHEMA,
222 },
223 drive: {
224 schema: DRIVE_NAME_SCHEMA,
225 },
226 "eject-media": {
227 description: "Eject media upon job completion.",
228 type: bool,
229 optional: true,
230 },
231 "export-media-set": {
232 description: "Export media set upon job completion.",
233 type: bool,
234 optional: true,
235 },
236 "latest-only": {
237 description: "Backup latest snapshots only.",
238 type: bool,
239 optional: true,
240 },
241 "notify-user": {
242 optional: true,
243 type: Userid,
244 },
245 }
246 )]
247 #[derive(Serialize,Deserialize,Clone,Updater)]
248 #[serde(rename_all="kebab-case")]
249 /// Tape Backup Job Setup
250 pub struct TapeBackupJobSetup {
251 pub store: String,
252 pub pool: String,
253 pub drive: String,
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>,
263 }
264
265 #[api(
266 properties: {
267 id: {
268 schema: JOB_ID_SCHEMA,
269 },
270 setup: {
271 type: TapeBackupJobSetup,
272 },
273 comment: {
274 optional: true,
275 schema: SINGLE_LINE_COMMENT_SCHEMA,
276 },
277 schedule: {
278 optional: true,
279 schema: SYNC_SCHEDULE_SCHEMA,
280 },
281 }
282 )]
283 #[derive(Serialize,Deserialize,Clone,Updater)]
284 #[serde(rename_all="kebab-case")]
285 /// Tape Backup Job
286 pub struct TapeBackupJobConfig {
287 #[updater(skip)]
288 pub id: String,
289 #[serde(flatten)]
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>,
295 }
296
297 #[api(
298 properties: {
299 config: {
300 type: TapeBackupJobConfig,
301 },
302 status: {
303 type: JobScheduleStatus,
304 },
305 },
306 )]
307 #[derive(Serialize,Deserialize)]
308 #[serde(rename_all="kebab-case")]
309 /// Status of Tape Backup Job
310 pub struct TapeBackupJobStatus {
311 #[serde(flatten)]
312 pub config: TapeBackupJobConfig,
313 #[serde(flatten)]
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>,
318 }
319
320 #[api(
321 properties: {
322 id: {
323 schema: JOB_ID_SCHEMA,
324 },
325 store: {
326 schema: DATASTORE_SCHEMA,
327 },
328 "owner": {
329 type: Authid,
330 optional: true,
331 },
332 remote: {
333 schema: REMOTE_ID_SCHEMA,
334 },
335 "remote-store": {
336 schema: DATASTORE_SCHEMA,
337 },
338 "remove-vanished": {
339 schema: REMOVE_VANISHED_BACKUPS_SCHEMA,
340 optional: true,
341 },
342 comment: {
343 optional: true,
344 schema: SINGLE_LINE_COMMENT_SCHEMA,
345 },
346 schedule: {
347 optional: true,
348 schema: SYNC_SCHEDULE_SCHEMA,
349 },
350 }
351 )]
352 #[derive(Serialize,Deserialize,Clone,Updater)]
353 #[serde(rename_all="kebab-case")]
354 /// Sync Job
355 pub struct SyncJobConfig {
356 #[updater(skip)]
357 pub id: String,
358 pub store: String,
359 #[serde(skip_serializing_if="Option::is_none")]
360 pub owner: Option<Authid>,
361 pub remote: String,
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>,
369 }
370
371 #[api(
372 properties: {
373 config: {
374 type: SyncJobConfig,
375 },
376 status: {
377 type: JobScheduleStatus,
378 },
379 },
380 )]
381
382 #[derive(Serialize,Deserialize)]
383 #[serde(rename_all="kebab-case")]
384 /// Status of Sync Job
385 pub struct SyncJobStatus {
386 #[serde(flatten)]
387 pub config: SyncJobConfig,
388 #[serde(flatten)]
389 pub status: JobScheduleStatus,
390 }