1 use anyhow
::{bail, Error}
;
4 use proxmox_router
::{cli::*, ApiHandler, RpcEnvironment}
;
5 use proxmox_schema
::api
;
6 use proxmox_section_config
::SectionConfigData
;
8 use pbs_config
::drive
::{
10 complete_changer_name
,
13 use pbs_api_types
::CHANGER_NAME_SCHEMA
;
15 use pbs_tape
::linux_list_drives
::{complete_changer_path}
;
17 use proxmox_backup
::{api2, tape::drive::media_changer}
;
19 pub fn lookup_changer_name(
21 config
: &SectionConfigData
,
22 ) -> Result
<String
, Error
> {
24 if let Some(name
) = param
["name"].as_str() {
25 return Ok(String
::from(name
));
28 let mut empty
= Value
::Null
;
30 if let Ok(drive
) = crate::extract_drive_name(&mut empty
, config
) {
31 if let Ok(Some((_
, name
))) = media_changer(config
, &drive
) {
36 bail
!("unable to get (default) changer name");
39 pub fn changer_commands() -> CommandLineInterface
{
41 let cmd_def
= CliCommandMap
::new()
42 .insert("scan", CliCommand
::new(&API_METHOD_SCAN_FOR_CHANGERS
))
43 .insert("list", CliCommand
::new(&API_METHOD_LIST_CHANGERS
))
45 CliCommand
::new(&API_METHOD_GET_CONFIG
)
47 .completion_cb("name", complete_changer_name
)
51 CliCommand
::new(&api2
::config
::changer
::API_METHOD_DELETE_CHANGER
)
53 .completion_cb("name", complete_changer_name
)
57 CliCommand
::new(&api2
::config
::changer
::API_METHOD_CREATE_CHANGER
)
59 .completion_cb("name", complete_drive_name
)
60 .completion_cb("path", complete_changer_path
)
64 CliCommand
::new(&api2
::config
::changer
::API_METHOD_UPDATE_CHANGER
)
66 .completion_cb("name", complete_changer_name
)
67 .completion_cb("path", complete_changer_path
)
70 CliCommand
::new(&API_METHOD_GET_STATUS
)
72 .completion_cb("name", complete_changer_name
)
75 CliCommand
::new(&API_METHOD_TRANSFER
)
77 .completion_cb("name", complete_changer_name
)
88 schema
: OUTPUT_FORMAT
,
97 rpcenv
: &mut dyn RpcEnvironment
,
98 ) -> Result
<(), Error
> {
100 let output_format
= get_output_format(¶m
);
101 let info
= &api2
::tape
::changer
::API_METHOD_LIST_CHANGERS
;
102 let mut data
= match info
.handler
{
103 ApiHandler
::Sync(handler
) => (handler
)(param
, info
, rpcenv
)?
,
107 let options
= default_table_format_options()
108 .column(ColumnConfig
::new("name"))
109 .column(ColumnConfig
::new("path"))
110 .column(ColumnConfig
::new("vendor"))
111 .column(ColumnConfig
::new("model"))
112 .column(ColumnConfig
::new("serial"))
115 format_and_print_result_full(&mut data
, &info
.returns
, &output_format
, &options
);
124 schema
: OUTPUT_FORMAT
,
130 /// Scan for SCSI tape changers
131 fn scan_for_changers(
133 rpcenv
: &mut dyn RpcEnvironment
,
134 ) -> Result
<(), Error
> {
136 let output_format
= get_output_format(¶m
);
137 let info
= &api2
::tape
::API_METHOD_SCAN_CHANGERS
;
138 let mut data
= match info
.handler
{
139 ApiHandler
::Sync(handler
) => (handler
)(param
, info
, rpcenv
)?
,
143 let options
= default_table_format_options()
144 .column(ColumnConfig
::new("path"))
145 .column(ColumnConfig
::new("vendor"))
146 .column(ColumnConfig
::new("model"))
147 .column(ColumnConfig
::new("serial"))
150 format_and_print_result_full(&mut data
, &info
.returns
, &output_format
, &options
);
159 schema
: OUTPUT_FORMAT
,
163 schema
: CHANGER_NAME_SCHEMA
,
168 /// Get tape changer configuration
171 rpcenv
: &mut dyn RpcEnvironment
,
172 ) -> Result
<(), Error
> {
174 let output_format
= get_output_format(¶m
);
175 let info
= &api2
::config
::changer
::API_METHOD_GET_CONFIG
;
176 let mut data
= match info
.handler
{
177 ApiHandler
::Sync(handler
) => (handler
)(param
, info
, rpcenv
)?
,
181 let options
= default_table_format_options()
182 .column(ColumnConfig
::new("name"))
183 .column(ColumnConfig
::new("path"))
184 .column(ColumnConfig
::new("export-slots"))
187 format_and_print_result_full(&mut data
, &info
.returns
, &output_format
, &options
);
196 schema
: OUTPUT_FORMAT
,
200 schema
: CHANGER_NAME_SCHEMA
,
204 description
: "Use cached value.",
212 /// Get tape changer status
215 rpcenv
: &mut dyn RpcEnvironment
,
216 ) -> Result
<(), Error
> {
218 let (config
, _digest
) = pbs_config
::drive
::config()?
;
220 param
["name"] = lookup_changer_name(¶m
, &config
)?
.into();
222 let output_format
= get_output_format(¶m
);
223 let info
= &api2
::tape
::changer
::API_METHOD_GET_STATUS
;
224 let mut data
= match info
.handler
{
225 ApiHandler
::Async(handler
) => (handler
)(param
, info
, rpcenv
).await?
,
229 let render_label_text
= |value
: &Value
, _record
: &Value
| -> Result
<String
, Error
> {
231 return Ok(String
::new());
233 let text
= value
.as_str().unwrap().to_string();
235 Ok(String
::from("--FULL--"))
241 let options
= default_table_format_options()
242 .sortby("entry-kind", false)
243 .sortby("entry-id", false)
244 .column(ColumnConfig
::new("entry-kind"))
245 .column(ColumnConfig
::new("entry-id"))
246 .column(ColumnConfig
::new("label-text").renderer(render_label_text
))
247 .column(ColumnConfig
::new("loaded-slot"))
250 format_and_print_result_full(&mut data
, &info
.returns
, &output_format
, &options
);
259 schema
: CHANGER_NAME_SCHEMA
,
263 description
: "Source slot number",
268 description
: "Destination slot number",
275 /// Transfers media from one slot to another
276 pub async
fn transfer(
278 rpcenv
: &mut dyn RpcEnvironment
,
279 ) -> Result
<(), Error
> {
281 let (config
, _digest
) = pbs_config
::drive
::config()?
;
283 param
["name"] = lookup_changer_name(¶m
, &config
)?
.into();
285 let info
= &api2
::tape
::changer
::API_METHOD_TRANSFER
;
287 ApiHandler
::Async(handler
) => (handler
)(param
, info
, rpcenv
).await?
,