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