1 use anyhow
::{bail, format_err, Error}
;
3 use ::serde
::{Deserialize, Serialize}
;
5 use proxmox
::api
::{api, Router, RpcEnvironment, schema::Updatable}
;
6 use proxmox
::tools
::fs
::open_file_locked
;
11 PROXMOX_CONFIG_DIGEST_SCHEMA
,
16 TAPE_JOB_CFG_LOCKFILE
,
18 TapeBackupJobConfigUpdater
,
28 description
: "List configured jobs.",
30 items
: { type: TapeBackupJobConfig }
,
33 /// List all tape backup jobs
34 pub fn list_tape_backup_jobs(
36 mut rpcenv
: &mut dyn RpcEnvironment
,
37 ) -> Result
<Vec
<TapeBackupJobConfig
>, Error
> {
39 let (config
, digest
) = config
::tape_job
::config()?
;
41 let list
= config
.convert_to_typed_array("backup")?
;
43 rpcenv
["digest"] = proxmox
::tools
::digest_to_hex(&digest
).into();
53 type: TapeBackupJobConfig
,
59 /// Create a new tape backup job.
60 pub fn create_tape_backup_job(
61 job
: TapeBackupJobConfig
,
62 _rpcenv
: &mut dyn RpcEnvironment
,
63 ) -> Result
<(), Error
> {
65 let _lock
= open_file_locked(TAPE_JOB_CFG_LOCKFILE
, std
::time
::Duration
::new(10, 0), true)?
;
67 let (mut config
, _digest
) = config
::tape_job
::config()?
;
69 if config
.sections
.get(&job
.id
).is_some() {
70 bail
!("job '{}' already exists.", job
.id
);
73 config
.set_data(&job
.id
, "backup", &job
)?
;
75 config
::tape_job
::save_config(&config
)?
;
77 crate::server
::jobstate
::create_state_file("tape-backup-job", &job
.id
)?
;
86 schema
: JOB_ID_SCHEMA
,
90 returns
: { type: TapeBackupJobConfig }
,
92 /// Read a tape backup job configuration.
93 pub fn read_tape_backup_job(
95 mut rpcenv
: &mut dyn RpcEnvironment
,
96 ) -> Result
<TapeBackupJobConfig
, Error
> {
98 let (config
, digest
) = config
::tape_job
::config()?
;
100 let job
= config
.lookup("backup", &id
)?
;
102 rpcenv
["digest"] = proxmox
::tools
::digest_to_hex(&digest
).into();
108 #[derive(Serialize, Deserialize)]
109 #[serde(rename_all="kebab-case")]
110 /// Deletable property name
111 pub enum DeletableProperty
{
112 /// Delete the comment property.
114 /// Delete the job schedule.
116 /// Delete the eject-media property
118 /// Delete the export-media-set property
120 /// Delete the 'latest-only' property
130 type: TapeBackupJobConfigUpdater
,
133 description
: "List of properties to delete.",
137 type: DeletableProperty
,
142 schema
: PROXMOX_CONFIG_DIGEST_SCHEMA
,
147 /// Update the tape backup job
148 pub fn update_tape_backup_job(
149 mut update
: TapeBackupJobConfigUpdater
,
150 delete
: Option
<Vec
<String
>>,
151 digest
: Option
<String
>,
152 ) -> Result
<(), Error
> {
153 let _lock
= open_file_locked(TAPE_JOB_CFG_LOCKFILE
, std
::time
::Duration
::new(10, 0), true)?
;
155 let id
= update
.id
.take().ok_or_else(|| format_err
!("no id given"))?
;
157 let (mut config
, expected_digest
) = config
::tape_job
::config()?
;
159 let mut job
: TapeBackupJobConfig
= config
.lookup("backup", &id
)?
;
161 if let Some(ref digest
) = digest
{
162 let digest
= proxmox
::tools
::hex_to_digest(digest
)?
;
163 crate::tools
::detect_modified_configuration_file(&digest
, &expected_digest
)?
;
166 job
.update_from(update
, &delete
.unwrap_or(Vec
::new()))?
;
168 config
.set_data(&job
.id
, "backup", &job
)?
;
170 config
::tape_job
::save_config(&config
)?
;
180 schema
: JOB_ID_SCHEMA
,
184 schema
: PROXMOX_CONFIG_DIGEST_SCHEMA
,
189 /// Remove a tape backup job configuration
190 pub fn delete_tape_backup_job(
192 digest
: Option
<String
>,
193 _rpcenv
: &mut dyn RpcEnvironment
,
194 ) -> Result
<(), Error
> {
195 let _lock
= open_file_locked(TAPE_JOB_CFG_LOCKFILE
, std
::time
::Duration
::new(10, 0), true)?
;
197 let (mut config
, expected_digest
) = config
::tape_job
::config()?
;
199 if let Some(ref digest
) = digest
{
200 let digest
= proxmox
::tools
::hex_to_digest(digest
)?
;
201 crate::tools
::detect_modified_configuration_file(&digest
, &expected_digest
)?
;
204 match config
.lookup
::<TapeBackupJobConfig
>("backup", &id
) {
206 config
.sections
.remove(&id
);
208 Err(_
) => { bail!("job '{}' does not exist
.", id) },
211 config::tape_job::save_config(&config)?;
213 crate::server::jobstate::remove_state_file("tape
-backup
-job
", &id)?;
218 const ITEM_ROUTER: Router = Router::new()
219 .get(&API_METHOD_READ_TAPE_BACKUP_JOB)
220 .put(&API_METHOD_UPDATE_TAPE_BACKUP_JOB)
221 .delete(&API_METHOD_DELETE_TAPE_BACKUP_JOB);
223 pub const ROUTER: Router = Router::new()
224 .get(&API_METHOD_LIST_TAPE_BACKUP_JOBS)
225 .post(&API_METHOD_CREATE_TAPE_BACKUP_JOB)
226 .match_all("id
", &ITEM_ROUTER);