]> git.proxmox.com Git - proxmox-backup.git/blame - src/api2/tape/drive.rs
tape: expose basic tape/changer functionality at api2/tape/
[proxmox-backup.git] / src / api2 / tape / drive.rs
CommitLineData
5d908606
DM
1use anyhow::{bail, Error};
2use serde_json::Value;
3
4use proxmox::api::{api, Router, SubdirMap};
5use proxmox::list_subdirs_api_method;
6
7use crate::{
8 config,
9 api2::types::{
10 DRIVE_ID_SCHEMA,
11 LinuxTapeDrive,
12 ScsiTapeChanger,
13 TapeDeviceInfo,
14 },
15 tape::{
16 MediaChange,
17 mtx_load,
18 mtx_unload,
19 linux_tape_device_list,
20 },
21};
22
23#[api(
24 input: {
25 properties: {
26 name: {
27 schema: DRIVE_ID_SCHEMA,
28 },
29 slot: {
30 description: "Source slot number",
31 minimum: 1,
32 },
33 },
34 },
35)]
36/// Load media via changer from slot
37pub fn load_slot(
38 name: String,
39 slot: u64,
40 _param: Value,
41) -> Result<(), Error> {
42
43 let (config, _digest) = config::drive::config()?;
44
45 let drive: LinuxTapeDrive = config.lookup("linux", &name)?;
46
47 let changer: ScsiTapeChanger = match drive.changer {
48 Some(ref changer) => config.lookup("changer", changer)?,
49 None => bail!("drive '{}' has no associated changer", name),
50 };
51
52 let drivenum = 0;
53
54 mtx_load(&changer.path, slot, drivenum)
55}
56
57#[api(
58 input: {
59 properties: {
60 name: {
61 schema: DRIVE_ID_SCHEMA,
62 },
63 slot: {
64 description: "Target slot number. If omitted, defaults to the slot that the drive was loaded from.",
65 minimum: 1,
66 optional: true,
67 },
68 },
69 },
70)]
71/// Unload media via changer
72pub fn unload(
73 name: String,
74 slot: Option<u64>,
75 _param: Value,
76) -> Result<(), Error> {
77
78 let (config, _digest) = config::drive::config()?;
79
80 let mut drive: LinuxTapeDrive = config.lookup("linux", &name)?;
81
82 let changer: ScsiTapeChanger = match drive.changer {
83 Some(ref changer) => config.lookup("changer", changer)?,
84 None => bail!("drive '{}' has no associated changer", name),
85 };
86
87 let drivenum: u64 = 0;
88
89 if let Some(slot) = slot {
90 mtx_unload(&changer.path, slot, drivenum)
91 } else {
92 drive.unload_media()
93 }
94}
95
96#[api(
97 input: {
98 properties: {},
99 },
100 returns: {
101 description: "The list of autodetected tape drives.",
102 type: Array,
103 items: {
104 type: TapeDeviceInfo,
105 },
106 },
107)]
108/// Scan tape drives
109pub fn scan_drives(_param: Value) -> Result<Vec<TapeDeviceInfo>, Error> {
110
111 let list = linux_tape_device_list();
112
113 Ok(list)
114}
115
116pub const SUBDIRS: SubdirMap = &[
117 (
118 "load-slot",
119 &Router::new()
120 .put(&API_METHOD_LOAD_SLOT)
121 ),
122 (
123 "scan",
124 &Router::new()
125 .get(&API_METHOD_SCAN_DRIVES)
126 ),
127 (
128 "unload",
129 &Router::new()
130 .put(&API_METHOD_UNLOAD)
131 ),
132];
133
134pub const ROUTER: Router = Router::new()
135 .get(&list_subdirs_api_method!(SUBDIRS))
136 .subdirs(SUBDIRS);