]> git.proxmox.com Git - proxmox-backup.git/blame - src/bin/proxmox_tape/drive.rs
tape: add command line interface proxmox-tape
[proxmox-backup.git] / src / bin / proxmox_tape / drive.rs
CommitLineData
e6604cf3
DM
1use anyhow::Error;
2use serde_json::Value;
3
4use proxmox::{
5 api::{
6 api,
7 cli::*,
8 RpcEnvironment,
9 ApiHandler,
10 },
11};
12
13use proxmox_backup::{
14 api2::{
15 self,
16 types::{
17 DRIVE_ID_SCHEMA,
18 CHANGER_ID_SCHEMA,
19 LINUX_DRIVE_PATH_SCHEMA,
20 },
21 },
22 tape::{
23 complete_drive_path,
24 },
25 config::drive::{
26 complete_drive_name,
27 complete_changer_name,
28 complete_linux_drive_name,
29 },
30};
31
32pub fn drive_commands() -> CommandLineInterface {
33
34 let cmd_def = CliCommandMap::new()
35 .insert("scan-for-drives", CliCommand::new(&API_METHOD_SCAN_FOR_DRIVES))
36 .insert("list", CliCommand::new(&API_METHOD_LIST_DRIVES))
37 .insert("config",
38 CliCommand::new(&API_METHOD_GET_CONFIG)
39 .arg_param(&["name"])
40 .completion_cb("name", complete_linux_drive_name)
41 )
42 .insert(
43 "remove",
44 CliCommand::new(&API_METHOD_DELETE_DRIVE)
45 .arg_param(&["name"])
46 .completion_cb("name", complete_linux_drive_name)
47 )
48 .insert(
49 "create",
50 CliCommand::new(&API_METHOD_CREATE_LINUX_DRIVE)
51 .arg_param(&["name"])
52 .completion_cb("name", complete_drive_name)
53 .completion_cb("path", complete_drive_path)
54 .completion_cb("changer", complete_changer_name)
55 )
56 .insert(
57 "update",
58 CliCommand::new(&API_METHOD_UPDATE_LINUX_DRIVE)
59 .arg_param(&["name"])
60 .completion_cb("name", complete_linux_drive_name)
61 .completion_cb("path", complete_drive_path)
62 .completion_cb("changer", complete_changer_name)
63 )
64 .insert(
65 "load",
66 CliCommand::new(&API_METHOD_LOAD_SLOT)
67 .arg_param(&["name"])
68 .completion_cb("name", complete_linux_drive_name)
69 )
70 .insert(
71 "unload",
72 CliCommand::new(&API_METHOD_UNLOAD)
73 .arg_param(&["name"])
74 .completion_cb("name", complete_linux_drive_name)
75 )
76 ;
77
78 cmd_def.into()
79}
80
81#[api(
82 input: {
83 properties: {
84 name: {
85 schema: DRIVE_ID_SCHEMA,
86 },
87 path: {
88 schema: LINUX_DRIVE_PATH_SCHEMA,
89 },
90 changer: {
91 schema: CHANGER_ID_SCHEMA,
92 optional: true,
93 },
94 },
95 },
96)]
97/// Create a new drive
98fn create_linux_drive(
99 param: Value,
100 rpcenv: &mut dyn RpcEnvironment,
101) -> Result<(), Error> {
102
103 let info = &api2::config::drive::API_METHOD_CREATE_DRIVE;
104 match info.handler {
105 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
106 _ => unreachable!(),
107 };
108
109 Ok(())
110}
111
112#[api(
113 input: {
114 properties: {
115 "output-format": {
116 schema: OUTPUT_FORMAT,
117 optional: true,
118 },
119 },
120 },
121)]
122/// List drives
123fn list_drives(
124 param: Value,
125 rpcenv: &mut dyn RpcEnvironment,
126) -> Result<(), Error> {
127
128 let output_format = get_output_format(&param);
129 let info = &api2::config::drive::API_METHOD_LIST_DRIVES;
130 let mut data = match info.handler {
131 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
132 _ => unreachable!(),
133 };
134
135 let options = default_table_format_options()
136 .column(ColumnConfig::new("name"))
137 .column(ColumnConfig::new("path"))
138 .column(ColumnConfig::new("changer"))
139 .column(ColumnConfig::new("vendor"))
140 .column(ColumnConfig::new("model"))
141 .column(ColumnConfig::new("serial"))
142 ;
143
144 format_and_print_result_full(&mut data, info.returns, &output_format, &options);
145
146 Ok(())
147}
148
149#[api(
150 input: {
151 properties: {
152 "output-format": {
153 schema: OUTPUT_FORMAT,
154 optional: true,
155 },
156 },
157 }
158)]
159/// Scan for drives
160fn scan_for_drives(
161 param: Value,
162 rpcenv: &mut dyn RpcEnvironment,
163) -> Result<(), Error> {
164
165 let output_format = get_output_format(&param);
166 let info = &api2::tape::drive::API_METHOD_SCAN_DRIVES;
167 let mut data = match info.handler {
168 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
169 _ => unreachable!(),
170 };
171
172 let options = default_table_format_options()
173 .column(ColumnConfig::new("path"))
174 .column(ColumnConfig::new("vendor"))
175 .column(ColumnConfig::new("model"))
176 .column(ColumnConfig::new("serial"))
177 ;
178
179 format_and_print_result_full(&mut data, info.returns, &output_format, &options);
180
181 Ok(())
182}
183
184
185#[api(
186 input: {
187 properties: {
188 "output-format": {
189 schema: OUTPUT_FORMAT,
190 optional: true,
191 },
192 name: {
193 schema: DRIVE_ID_SCHEMA,
194 },
195 },
196 },
197)]
198/// Get pool configuration
199fn get_config(
200 param: Value,
201 rpcenv: &mut dyn RpcEnvironment,
202) -> Result<(), Error> {
203
204 let output_format = get_output_format(&param);
205 let info = &api2::config::drive::API_METHOD_GET_CONFIG;
206 let mut data = match info.handler {
207 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
208 _ => unreachable!(),
209 };
210
211 let options = default_table_format_options()
212 .column(ColumnConfig::new("name"))
213 .column(ColumnConfig::new("path"))
214 .column(ColumnConfig::new("changer"))
215 ;
216
217 format_and_print_result_full(&mut data, info.returns, &output_format, &options);
218
219 Ok(())
220}
221
222#[api(
223 input: {
224 properties: {
225 name: {
226 schema: DRIVE_ID_SCHEMA,
227 },
228 },
229 },
230)]
231/// Delete a drive configuration
232fn delete_drive(
233 param: Value,
234 rpcenv: &mut dyn RpcEnvironment,
235) -> Result<(), Error> {
236
237 let info = &api2::config::drive::API_METHOD_DELETE_DRIVE;
238
239 match info.handler {
240 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
241 _ => unreachable!(),
242 };
243
244 Ok(())
245}
246
247#[api(
248 input: {
249 properties: {
250 name: {
251 schema: DRIVE_ID_SCHEMA,
252 },
253 path: {
254 schema: LINUX_DRIVE_PATH_SCHEMA,
255 optional: true,
256 },
257 changer: {
258 schema: CHANGER_ID_SCHEMA,
259 optional: true,
260 },
261 },
262 },
263)]
264/// Update a drive configuration
265fn update_linux_drive(
266 param: Value,
267 rpcenv: &mut dyn RpcEnvironment,
268) -> Result<(), Error> {
269
270 let info = &api2::config::drive::API_METHOD_UPDATE_DRIVE;
271
272 match info.handler {
273 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
274 _ => unreachable!(),
275 };
276
277 Ok(())
278}
279
280#[api(
281 input: {
282 properties: {
283 name: {
284 schema: DRIVE_ID_SCHEMA,
285 },
286 slot: {
287 type: u64,
288 description: "Source slot number",
289 minimum: 1,
290 },
291 },
292 },
293)]
294/// Load media via changer from slot
295fn load_slot(
296 param: Value,
297 rpcenv: &mut dyn RpcEnvironment,
298) -> Result<(), Error> {
299
300 let info = &api2::tape::drive::API_METHOD_LOAD_SLOT;
301
302 match info.handler {
303 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
304 _ => unreachable!(),
305 };
306
307 Ok(())
308}
309
310#[api(
311 input: {
312 properties: {
313 name: {
314 schema: DRIVE_ID_SCHEMA,
315 },
316 slot: {
317 description: "Target slot number. If omitted, defaults to the slot that the drive was loaded from.",
318 type: u64,
319 minimum: 1,
320 optional: true,
321 },
322 },
323 },
324)]
325/// Unload media via changer
326fn unload(
327 param: Value,
328 rpcenv: &mut dyn RpcEnvironment,
329) -> Result<(), Error> {
330
331 let info = &api2::tape::drive::API_METHOD_UNLOAD;
332
333 match info.handler {
334 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
335 _ => unreachable!(),
336 };
337
338 Ok(())
339}