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