]>
Commit | Line | Data |
---|---|---|
e7cb4dc5 WB |
1 | use std::collections::HashMap; |
2 | ||
d43f86f3 DC |
3 | use anyhow::{Error}; |
4 | use serde_json::Value; | |
d43f86f3 DC |
5 | |
6 | use proxmox::api::{api, ApiMethod, Router, RpcEnvironment}; | |
7 | use proxmox::api::router::SubdirMap; | |
8 | use proxmox::{list_subdirs_api_method, sortable}; | |
9 | ||
10 | use crate::api2::types::*; | |
11 | use crate::api2::pull::{get_pull_parameters}; | |
12 | use crate::config::sync::{self, SyncJobStatus, SyncJobConfig}; | |
13 | use crate::server::{self, TaskListInfo, WorkerTask}; | |
14 | use crate::tools::systemd::time::{ | |
15 | parse_calendar_event, compute_next_event}; | |
16 | ||
17 | #[api( | |
18 | input: { | |
19 | properties: {}, | |
20 | }, | |
21 | returns: { | |
22 | description: "List configured jobs and their status.", | |
23 | type: Array, | |
24 | items: { type: sync::SyncJobStatus }, | |
25 | }, | |
26 | )] | |
27 | /// List all sync jobs | |
28 | pub fn list_sync_jobs( | |
29 | _param: Value, | |
30 | mut rpcenv: &mut dyn RpcEnvironment, | |
31 | ) -> Result<Vec<SyncJobStatus>, Error> { | |
32 | ||
33 | let (config, digest) = sync::config()?; | |
34 | ||
35 | let mut list: Vec<SyncJobStatus> = config.convert_to_typed_array("sync")?; | |
36 | ||
37 | let mut last_tasks: HashMap<String, &TaskListInfo> = HashMap::new(); | |
38 | let tasks = server::read_task_list()?; | |
39 | ||
40 | for info in tasks.iter() { | |
41 | let worker_id = match &info.upid.worker_id { | |
42 | Some(id) => id, | |
43 | _ => { continue; }, | |
44 | }; | |
45 | if let Some(last) = last_tasks.get(worker_id) { | |
46 | if last.upid.starttime < info.upid.starttime { | |
47 | last_tasks.insert(worker_id.to_string(), &info); | |
48 | } | |
49 | } else { | |
50 | last_tasks.insert(worker_id.to_string(), &info); | |
51 | } | |
52 | } | |
53 | ||
d43f86f3 | 54 | for job in &mut list { |
8d785899 | 55 | let mut last = 0; |
d43f86f3 DC |
56 | if let Some(task) = last_tasks.get(&job.id) { |
57 | job.last_run_upid = Some(task.upid_str.clone()); | |
8d785899 | 58 | if let Some((endtime, status)) = &task.state { |
4c116baf | 59 | job.last_run_state = Some(status.to_string()); |
8d785899 DC |
60 | job.last_run_endtime = Some(*endtime); |
61 | last = *endtime; | |
d43f86f3 DC |
62 | } |
63 | } | |
8d785899 DC |
64 | |
65 | job.next_run = (|| -> Option<i64> { | |
66 | let schedule = job.schedule.as_ref()?; | |
67 | let event = parse_calendar_event(&schedule).ok()?; | |
68 | compute_next_event(&event, last, false).ok() | |
69 | })(); | |
d43f86f3 DC |
70 | } |
71 | ||
72 | rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into(); | |
73 | ||
74 | Ok(list) | |
75 | } | |
76 | ||
77 | #[api( | |
78 | input: { | |
79 | properties: { | |
80 | id: { | |
81 | schema: JOB_ID_SCHEMA, | |
82 | } | |
83 | } | |
84 | } | |
85 | )] | |
86 | /// Runs the sync jobs manually. | |
87 | async fn run_sync_job( | |
88 | id: String, | |
89 | _info: &ApiMethod, | |
90 | rpcenv: &mut dyn RpcEnvironment, | |
91 | ) -> Result<String, Error> { | |
92 | ||
93 | let (config, _digest) = sync::config()?; | |
94 | let sync_job: SyncJobConfig = config.lookup("sync", &id)?; | |
95 | ||
e7cb4dc5 | 96 | let userid: Userid = rpcenv.get_user().unwrap().parse()?; |
d43f86f3 DC |
97 | |
98 | let delete = sync_job.remove_vanished.unwrap_or(true); | |
99 | let (client, src_repo, tgt_store) = get_pull_parameters(&sync_job.store, &sync_job.remote, &sync_job.remote_store).await?; | |
100 | ||
e7cb4dc5 | 101 | let upid_str = WorkerTask::spawn("syncjob", Some(id.clone()), userid, false, move |worker| async move { |
d43f86f3 DC |
102 | |
103 | worker.log(format!("sync job '{}' start", &id)); | |
104 | ||
e7cb4dc5 WB |
105 | crate::client::pull::pull_store( |
106 | &worker, | |
107 | &client, | |
108 | &src_repo, | |
109 | tgt_store.clone(), | |
110 | delete, | |
111 | Userid::backup_userid().clone(), | |
112 | ).await?; | |
d43f86f3 DC |
113 | |
114 | worker.log(format!("sync job '{}' end", &id)); | |
115 | ||
116 | Ok(()) | |
117 | })?; | |
118 | ||
119 | Ok(upid_str) | |
120 | } | |
121 | ||
122 | #[sortable] | |
123 | const SYNC_INFO_SUBDIRS: SubdirMap = &[ | |
124 | ( | |
125 | "run", | |
126 | &Router::new() | |
127 | .post(&API_METHOD_RUN_SYNC_JOB) | |
128 | ), | |
129 | ]; | |
130 | ||
131 | const SYNC_INFO_ROUTER: Router = Router::new() | |
132 | .get(&list_subdirs_api_method!(SYNC_INFO_SUBDIRS)) | |
133 | .subdirs(SYNC_INFO_SUBDIRS); | |
134 | ||
135 | ||
136 | pub const ROUTER: Router = Router::new() | |
137 | .get(&API_METHOD_LIST_SYNC_JOBS) | |
138 | .match_all("id", &SYNC_INFO_ROUTER); |