1 use anyhow
::{bail, Error}
;
4 use proxmox
::api
::{api, Router, RpcEnvironment}
;
9 PROXMOX_CONFIG_DIGEST_SCHEMA
,
11 LINUX_DRIVE_PATH_SCHEMA
,
17 linux_tape_changer_list
,
28 schema
: CHANGER_NAME_SCHEMA
,
31 schema
: LINUX_DRIVE_PATH_SCHEMA
,
36 /// Create a new changer device
37 pub fn create_changer(
40 ) -> Result
<(), Error
> {
42 let _lock
= config
::drive
::lock()?
;
44 let (mut config
, _digest
) = config
::drive
::config()?
;
46 let linux_changers
= linux_tape_changer_list();
48 check_drive_path(&linux_changers
, &path
)?
;
50 if config
.sections
.get(&name
).is_some() {
51 bail
!("Entry '{}' already exists", name
);
54 let item
= ScsiTapeChanger
{
59 config
.set_data(&name
, "changer", &item
)?
;
61 config
::drive
::save_config(&config
)?
;
70 schema
: CHANGER_NAME_SCHEMA
,
75 type: ScsiTapeChanger
,
79 /// Get tape changer configuration
83 mut rpcenv
: &mut dyn RpcEnvironment
,
84 ) -> Result
<ScsiTapeChanger
, Error
> {
86 let (config
, digest
) = config
::drive
::config()?
;
88 let data
: ScsiTapeChanger
= config
.lookup("changer", &name
)?
;
90 rpcenv
["digest"] = proxmox
::tools
::digest_to_hex(&digest
).into();
100 description
: "The list of configured changers (with config digest).",
103 type: DriveListEntry
,
108 pub fn list_changers(
110 mut rpcenv
: &mut dyn RpcEnvironment
,
111 ) -> Result
<Vec
<DriveListEntry
>, Error
> {
113 let (config
, digest
) = config
::drive
::config()?
;
115 let linux_changers
= linux_tape_changer_list();
117 let changer_list
: Vec
<ScsiTapeChanger
> = config
.convert_to_typed_array("changer")?
;
119 let mut list
= Vec
::new();
121 for changer
in changer_list
{
122 let mut entry
= DriveListEntry
{
124 path
: changer
.path
.clone(),
130 if let Some(info
) = lookup_drive(&linux_changers
, &changer
.path
) {
131 entry
.vendor
= Some(info
.vendor
.clone());
132 entry
.model
= Some(info
.model
.clone());
133 entry
.serial
= Some(info
.serial
.clone());
139 rpcenv
["digest"] = proxmox
::tools
::digest_to_hex(&digest
).into();
148 schema
: CHANGER_NAME_SCHEMA
,
151 schema
: LINUX_DRIVE_PATH_SCHEMA
,
155 schema
: PROXMOX_CONFIG_DIGEST_SCHEMA
,
161 /// Update a tape changer configuration
162 pub fn update_changer(
164 path
: Option
<String
>,
165 digest
: Option
<String
>,
167 ) -> Result
<(), Error
> {
169 let _lock
= config
::drive
::lock()?
;
171 let (mut config
, expected_digest
) = config
::drive
::config()?
;
173 if let Some(ref digest
) = digest
{
174 let digest
= proxmox
::tools
::hex_to_digest(digest
)?
;
175 crate::tools
::detect_modified_configuration_file(&digest
, &expected_digest
)?
;
178 let mut data
: ScsiTapeChanger
= config
.lookup("changer", &name
)?
;
180 if let Some(path
) = path
{
181 let changers
= linux_tape_changer_list();
182 check_drive_path(&changers
, &path
)?
;
186 config
.set_data(&name
, "changer", &data
)?
;
188 config
::drive
::save_config(&config
)?
;
198 schema
: CHANGER_NAME_SCHEMA
,
203 /// Delete a tape changer configuration
204 pub fn delete_changer(name
: String
, _param
: Value
) -> Result
<(), Error
> {
206 let _lock
= config
::drive
::lock()?
;
208 let (mut config
, _digest
) = config
::drive
::config()?
;
210 match config
.sections
.get(&name
) {
211 Some((section_type
, _
)) => {
212 if section_type
!= "changer" {
213 bail
!("Entry '{}' exists, but is not a changer device", name
);
215 config
.sections
.remove(&name
);
217 None
=> bail
!("Delete changer '{}' failed - no such entry", name
),
220 let drive_list
: Vec
<LinuxTapeDrive
> = config
.convert_to_typed_array("linux")?
;
221 for drive
in drive_list
{
222 if let Some(changer
) = drive
.changer
{
224 bail
!("Delete changer '{}' failed - used by drive '{}'", name
, drive
.name
);
229 config
::drive
::save_config(&config
)?
;
234 const ITEM_ROUTER
: Router
= Router
::new()
235 .get(&API_METHOD_GET_CONFIG
)
236 .put(&API_METHOD_UPDATE_CHANGER
)
237 .delete(&API_METHOD_DELETE_CHANGER
);
240 pub const ROUTER
: Router
= Router
::new()
241 .get(&API_METHOD_LIST_CHANGERS
)
242 .post(&API_METHOD_CREATE_CHANGER
)
243 .match_all("name", &ITEM_ROUTER
);