]>
Commit | Line | Data |
---|---|---|
5d908606 DM |
1 | use anyhow::{bail, Error}; |
2 | use serde_json::Value; | |
3 | ||
4 | use proxmox::api::{api, Router, SubdirMap}; | |
5 | use proxmox::list_subdirs_api_method; | |
6 | ||
7 | use 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 | |
37 | pub 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 | |
72 | pub 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 | |
109 | pub fn scan_drives(_param: Value) -> Result<Vec<TapeDeviceInfo>, Error> { | |
110 | ||
111 | let list = linux_tape_device_list(); | |
112 | ||
113 | Ok(list) | |
114 | } | |
115 | ||
116 | pub 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 | ||
134 | pub const ROUTER: Router = Router::new() | |
135 | .get(&list_subdirs_api_method!(SUBDIRS)) | |
136 | .subdirs(SUBDIRS); |