]>
Commit | Line | Data |
---|---|---|
50bf10ad DM |
1 | use anyhow::{bail, Error}; |
2 | use serde_json::Value; | |
3 | ||
4 | use proxmox::api::{api, Router, RpcEnvironment}; | |
5 | ||
6 | use crate::{ | |
7 | config, | |
8 | api2::types::{ | |
5ba83ed0 | 9 | PROXMOX_CONFIG_DIGEST_SCHEMA, |
50bf10ad DM |
10 | CHANGER_ID_SCHEMA, |
11 | LINUX_DRIVE_PATH_SCHEMA, | |
12 | DriveListEntry, | |
13 | ScsiTapeChanger, | |
50bf10ad DM |
14 | }, |
15 | tape::{ | |
16 | linux_tape_changer_list, | |
17 | check_drive_path, | |
18 | lookup_drive, | |
19 | }, | |
20 | }; | |
21 | ||
22 | #[api( | |
314652a4 | 23 | protected: true, |
50bf10ad DM |
24 | input: { |
25 | properties: { | |
26 | name: { | |
27 | schema: CHANGER_ID_SCHEMA, | |
28 | }, | |
29 | path: { | |
30 | schema: LINUX_DRIVE_PATH_SCHEMA, | |
31 | }, | |
32 | }, | |
33 | }, | |
34 | )] | |
35 | /// Create a new changer device | |
36 | pub fn create_changer( | |
37 | name: String, | |
38 | path: String, | |
39 | ) -> Result<(), Error> { | |
40 | ||
41 | let _lock = config::drive::lock()?; | |
42 | ||
43 | let (mut config, _digest) = config::drive::config()?; | |
44 | ||
45 | let linux_changers = linux_tape_changer_list(); | |
46 | ||
47 | check_drive_path(&linux_changers, &path)?; | |
48 | ||
49 | if config.sections.get(&name).is_some() { | |
50 | bail!("Entry '{}' already exists", name); | |
51 | } | |
52 | ||
53 | let item = ScsiTapeChanger { | |
54 | name: name.clone(), | |
55 | path, | |
56 | }; | |
57 | ||
58 | config.set_data(&name, "changer", &item)?; | |
59 | ||
60 | config::drive::save_config(&config)?; | |
61 | ||
62 | Ok(()) | |
63 | } | |
64 | ||
65 | #[api( | |
66 | input: { | |
67 | properties: { | |
68 | name: { | |
69 | schema: CHANGER_ID_SCHEMA, | |
70 | }, | |
71 | }, | |
72 | }, | |
73 | returns: { | |
74 | type: ScsiTapeChanger, | |
75 | }, | |
76 | ||
77 | )] | |
78 | /// Get tape changer configuration | |
79 | pub fn get_config( | |
80 | name: String, | |
81 | _param: Value, | |
82 | mut rpcenv: &mut dyn RpcEnvironment, | |
83 | ) -> Result<ScsiTapeChanger, Error> { | |
84 | ||
85 | let (config, digest) = config::drive::config()?; | |
86 | ||
87 | let data: ScsiTapeChanger = config.lookup("changer", &name)?; | |
88 | ||
89 | rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into(); | |
90 | ||
91 | Ok(data) | |
92 | } | |
93 | ||
94 | #[api( | |
95 | input: { | |
96 | properties: {}, | |
97 | }, | |
98 | returns: { | |
99 | description: "The list of configured changers (with config digest).", | |
100 | type: Array, | |
101 | items: { | |
102 | type: DriveListEntry, | |
103 | }, | |
104 | }, | |
105 | )] | |
106 | /// List changers | |
107 | pub fn list_changers( | |
108 | _param: Value, | |
109 | mut rpcenv: &mut dyn RpcEnvironment, | |
110 | ) -> Result<Vec<DriveListEntry>, Error> { | |
111 | ||
112 | let (config, digest) = config::drive::config()?; | |
113 | ||
114 | let linux_changers = linux_tape_changer_list(); | |
115 | ||
116 | let changer_list: Vec<ScsiTapeChanger> = config.convert_to_typed_array("changer")?; | |
117 | ||
118 | let mut list = Vec::new(); | |
119 | ||
120 | for changer in changer_list { | |
121 | let mut entry = DriveListEntry { | |
122 | name: changer.name, | |
123 | path: changer.path.clone(), | |
124 | changer: None, | |
125 | vendor: None, | |
126 | model: None, | |
127 | serial: None, | |
128 | }; | |
129 | if let Some(info) = lookup_drive(&linux_changers, &changer.path) { | |
130 | entry.vendor = Some(info.vendor.clone()); | |
131 | entry.model = Some(info.model.clone()); | |
132 | entry.serial = Some(info.serial.clone()); | |
133 | } | |
134 | ||
135 | list.push(entry); | |
136 | } | |
137 | ||
138 | rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into(); | |
139 | Ok(list) | |
140 | } | |
141 | ||
142 | #[api( | |
314652a4 | 143 | protected: true, |
50bf10ad DM |
144 | input: { |
145 | properties: { | |
146 | name: { | |
147 | schema: CHANGER_ID_SCHEMA, | |
148 | }, | |
149 | path: { | |
150 | schema: LINUX_DRIVE_PATH_SCHEMA, | |
151 | optional: true, | |
152 | }, | |
5ba83ed0 DM |
153 | digest: { |
154 | schema: PROXMOX_CONFIG_DIGEST_SCHEMA, | |
155 | optional: true, | |
156 | }, | |
157 | }, | |
50bf10ad DM |
158 | }, |
159 | )] | |
160 | /// Update a tape changer configuration | |
161 | pub fn update_changer( | |
162 | name: String, | |
163 | path: Option<String>, | |
5ba83ed0 | 164 | digest: Option<String>, |
50bf10ad DM |
165 | _param: Value, |
166 | ) -> Result<(), Error> { | |
167 | ||
168 | let _lock = config::drive::lock()?; | |
169 | ||
5ba83ed0 DM |
170 | let (mut config, expected_digest) = config::drive::config()?; |
171 | ||
172 | if let Some(ref digest) = digest { | |
173 | let digest = proxmox::tools::hex_to_digest(digest)?; | |
174 | crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?; | |
175 | } | |
50bf10ad DM |
176 | |
177 | let mut data: ScsiTapeChanger = config.lookup("changer", &name)?; | |
178 | ||
179 | if let Some(path) = path { | |
180 | let changers = linux_tape_changer_list(); | |
181 | check_drive_path(&changers, &path)?; | |
182 | data.path = path; | |
183 | } | |
184 | ||
185 | config.set_data(&name, "changer", &data)?; | |
186 | ||
187 | config::drive::save_config(&config)?; | |
188 | ||
189 | Ok(()) | |
190 | } | |
191 | ||
192 | #[api( | |
314652a4 | 193 | protected: true, |
50bf10ad DM |
194 | input: { |
195 | properties: { | |
196 | name: { | |
197 | schema: CHANGER_ID_SCHEMA, | |
198 | }, | |
199 | }, | |
200 | }, | |
201 | )] | |
202 | /// Delete a tape changer configuration | |
203 | pub fn delete_changer(name: String, _param: Value) -> Result<(), Error> { | |
204 | ||
205 | let _lock = config::drive::lock()?; | |
206 | ||
207 | let (mut config, _digest) = config::drive::config()?; | |
208 | ||
209 | match config.sections.get(&name) { | |
210 | Some((section_type, _)) => { | |
211 | if section_type != "changer" { | |
212 | bail!("Entry '{}' exists, but is not a changer device", name); | |
213 | } | |
214 | config.sections.remove(&name); | |
215 | }, | |
216 | None => bail!("Delete changer '{}' failed - no such entry", name), | |
217 | } | |
218 | ||
219 | config::drive::save_config(&config)?; | |
220 | ||
221 | Ok(()) | |
222 | } | |
223 | ||
50bf10ad DM |
224 | const ITEM_ROUTER: Router = Router::new() |
225 | .get(&API_METHOD_GET_CONFIG) | |
226 | .put(&API_METHOD_UPDATE_CHANGER) | |
227 | .delete(&API_METHOD_DELETE_CHANGER); | |
228 | ||
229 | ||
230 | pub const ROUTER: Router = Router::new() | |
231 | .get(&API_METHOD_LIST_CHANGERS) | |
232 | .post(&API_METHOD_CREATE_CHANGER) | |
233 | .match_all("name", &ITEM_ROUTER); |