]> git.proxmox.com Git - proxmox-backup.git/blame - src/bin/proxmox_tape/media.rs
update to first proxmox crate split
[proxmox-backup.git] / src / bin / proxmox_tape / media.rs
CommitLineData
fba0b774
DM
1use anyhow::{Error};
2use serde_json::Value;
3
6ef1b649
WB
4use proxmox_router::{cli::*, ApiHandler, RpcEnvironment};
5use proxmox_schema::api;
fba0b774 6
1ce8e905
DM
7use pbs_api_types::{
8 MEDIA_POOL_NAME_SCHEMA, CHANGER_NAME_SCHEMA, MediaStatus, MediaListEntry,
9 MediaContentListFilter,
10};
11use pbs_config::drive::complete_changer_name;
aad2d162 12use pbs_config::media_pool::complete_pool_name;
1ce8e905 13
fba0b774 14use proxmox_backup::{
1ce8e905 15 api2,
a33389c3 16 tape::{
8446fbca 17 complete_media_label_text,
a33389c3
DM
18 complete_media_uuid,
19 complete_media_set_uuid,
fba0b774 20 },
fba0b774
DM
21};
22
23pub fn media_commands() -> CommandLineInterface {
24
25 let cmd_def = CliCommandMap::new()
26 .insert(
27 "list",
28 CliCommand::new(&API_METHOD_LIST_MEDIA)
29 .completion_cb("pool", complete_pool_name)
9bbd83b1 30 .completion_cb("update-status-changer", complete_changer_name)
fba0b774 31 )
fb657d8e 32 .insert(
e20d008c 33 "destroy",
fb657d8e 34 CliCommand::new(&api2::tape::media::API_METHOD_DESTROY_MEDIA)
8446fbca
DM
35 .arg_param(&["label-text"])
36 .completion_cb("label-text", complete_media_label_text)
fb657d8e 37 )
a33389c3
DM
38 .insert(
39 "content",
40 CliCommand::new(&API_METHOD_LIST_CONTENT)
41 .completion_cb("pool", complete_pool_name)
8446fbca 42 .completion_cb("label-text", complete_media_label_text)
a33389c3
DM
43 .completion_cb("media", complete_media_uuid)
44 .completion_cb("media-set", complete_media_set_uuid)
45 )
fba0b774
DM
46 ;
47
48 cmd_def.into()
49}
50
51#[api(
52 input: {
53 properties: {
54 pool: {
55 schema: MEDIA_POOL_NAME_SCHEMA,
56 optional: true,
57 },
9bbd83b1
DM
58 "update-status": {
59 description: "Try to update tape library status (check what tapes are online).",
60 type: bool,
61 optional: true,
62 default: true,
63 },
64 "update-status-changer": {
65 // only update status for a single changer
66 schema: CHANGER_NAME_SCHEMA,
67 optional: true,
68 },
fba0b774
DM
69 "output-format": {
70 schema: OUTPUT_FORMAT,
71 optional: true,
72 },
73 },
74 },
75)]
76/// List pool media
77async fn list_media(
78 param: Value,
79 rpcenv: &mut dyn RpcEnvironment,
80) -> Result<(), Error> {
81
82 let output_format = get_output_format(&param);
83 let info = &api2::tape::media::API_METHOD_LIST_MEDIA;
84 let mut data = match info.handler {
85 ApiHandler::Async(handler) => (handler)(param, info, rpcenv).await?,
86 _ => unreachable!(),
87 };
88
fba0b774
DM
89 fn render_status(_value: &Value, record: &Value) -> Result<String, Error> {
90 let record: MediaListEntry = serde_json::from_value(record.clone())?;
91 Ok(match record.status {
92 MediaStatus::Damaged | MediaStatus::Retired => {
93 serde_json::to_value(&record.status)?
94 .as_str().unwrap()
95 .to_string()
96 }
97 _ => {
98 if record.expired {
99 String::from("expired")
100 } else {
101 serde_json::to_value(&record.status)?
102 .as_str().unwrap()
103 .to_string()
104 }
105 }
106 })
107 }
108
0bf1c314
DM
109 fn catalog_status(value: &Value, _record: &Value) -> Result<String, Error> {
110 let catalog_ok = value.as_bool().unwrap();
111 if catalog_ok {
112 Ok(String::from("ok"))
113 } else {
114 Ok(String::from("missing"))
115 }
116 }
fba0b774
DM
117 let options = default_table_format_options()
118 .sortby("pool", false)
119 .sortby("media-set-uuid", false)
120 .sortby("seq-nr", false)
8446fbca
DM
121 .sortby("label-text", false)
122 .column(ColumnConfig::new("label-text"))
fba0b774
DM
123 .column(ColumnConfig::new("pool"))
124 .column(ColumnConfig::new("media-set-name"))
125 .column(ColumnConfig::new("seq-nr"))
126 .column(ColumnConfig::new("status").renderer(render_status))
c1c2c8f6 127 .column(ColumnConfig::new("location"))
0bf1c314 128 .column(ColumnConfig::new("catalog").renderer(catalog_status))
fba0b774
DM
129 .column(ColumnConfig::new("uuid"))
130 .column(ColumnConfig::new("media-set-uuid"))
131 ;
132
b2362a12 133 format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
fba0b774
DM
134
135 Ok(())
136}
a33389c3
DM
137
138#[api(
139 input: {
140 properties: {
141 "filter": {
142 type: MediaContentListFilter,
143 flatten: true,
144 },
145 "output-format": {
146 schema: OUTPUT_FORMAT,
147 optional: true,
148 },
149 },
150 },
151)]
152/// List media content
153fn list_content(
154 param: Value,
155 rpcenv: &mut dyn RpcEnvironment,
156) -> Result<(), Error> {
157
158 let output_format = get_output_format(&param);
159 let info = &api2::tape::media::API_METHOD_LIST_CONTENT;
160 let mut data = match info.handler {
161 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
162 _ => unreachable!(),
163 };
164
165 let options = default_table_format_options()
166 .sortby("media-set-uuid", false)
167 .sortby("seq-nr", false)
ef4bdf6b 168 .sortby("store", false)
a33389c3
DM
169 .sortby("snapshot", false)
170 .sortby("backup-time", false)
8446fbca 171 .column(ColumnConfig::new("label-text"))
a33389c3
DM
172 .column(ColumnConfig::new("pool"))
173 .column(ColumnConfig::new("media-set-name"))
174 .column(ColumnConfig::new("seq-nr"))
ef4bdf6b 175 .column(ColumnConfig::new("store"))
a33389c3
DM
176 .column(ColumnConfig::new("snapshot"))
177 .column(ColumnConfig::new("media-set-uuid"))
178 ;
179
180 format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
181
182 Ok(())
183
184}