]> git.proxmox.com Git - proxmox-backup.git/blame - src/api2/config/changer.rs
tape: add changer property to drive create api
[proxmox-backup.git] / src / api2 / config / changer.rs
CommitLineData
50bf10ad
DM
1use anyhow::{bail, Error};
2use serde_json::Value;
3
4use proxmox::api::{api, Router, RpcEnvironment};
5
6use crate::{
7 config,
8 api2::types::{
5ba83ed0 9 PROXMOX_CONFIG_DIGEST_SCHEMA,
50bf10ad
DM
10 CHANGER_ID_SCHEMA,
11 LINUX_DRIVE_PATH_SCHEMA,
12 DriveListEntry,
13 ScsiTapeChanger,
50bf10ad
DM
14 },
15 tape::{
16 linux_tape_changer_list,
17 check_drive_path,
18 lookup_drive,
19 },
20};
21
22#[api(
314652a4 23 protected: true,
50bf10ad
DM
24 input: {
25 properties: {
26 name: {
27 schema: CHANGER_ID_SCHEMA,
28 },
29 path: {
30 schema: LINUX_DRIVE_PATH_SCHEMA,
31 },
32 },
33 },
34)]
35/// Create a new changer device
36pub fn create_changer(
37 name: String,
38 path: String,
39) -> Result<(), Error> {
40
41 let _lock = config::drive::lock()?;
42
43 let (mut config, _digest) = config::drive::config()?;
44
45 let linux_changers = linux_tape_changer_list();
46
47 check_drive_path(&linux_changers, &path)?;
48
49 if config.sections.get(&name).is_some() {
50 bail!("Entry '{}' already exists", name);
51 }
52
53 let item = ScsiTapeChanger {
54 name: name.clone(),
55 path,
56 };
57
58 config.set_data(&name, "changer", &item)?;
59
60 config::drive::save_config(&config)?;
61
62 Ok(())
63}
64
65#[api(
66 input: {
67 properties: {
68 name: {
69 schema: CHANGER_ID_SCHEMA,
70 },
71 },
72 },
73 returns: {
74 type: ScsiTapeChanger,
75 },
76
77)]
78/// Get tape changer configuration
79pub fn get_config(
80 name: String,
81 _param: Value,
82 mut rpcenv: &mut dyn RpcEnvironment,
83) -> Result<ScsiTapeChanger, Error> {
84
85 let (config, digest) = config::drive::config()?;
86
87 let data: ScsiTapeChanger = config.lookup("changer", &name)?;
88
89 rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
90
91 Ok(data)
92}
93
94#[api(
95 input: {
96 properties: {},
97 },
98 returns: {
99 description: "The list of configured changers (with config digest).",
100 type: Array,
101 items: {
102 type: DriveListEntry,
103 },
104 },
105)]
106/// List changers
107pub fn list_changers(
108 _param: Value,
109 mut rpcenv: &mut dyn RpcEnvironment,
110) -> Result<Vec<DriveListEntry>, Error> {
111
112 let (config, digest) = config::drive::config()?;
113
114 let linux_changers = linux_tape_changer_list();
115
116 let changer_list: Vec<ScsiTapeChanger> = config.convert_to_typed_array("changer")?;
117
118 let mut list = Vec::new();
119
120 for changer in changer_list {
121 let mut entry = DriveListEntry {
122 name: changer.name,
123 path: changer.path.clone(),
124 changer: None,
125 vendor: None,
126 model: None,
127 serial: None,
128 };
129 if let Some(info) = lookup_drive(&linux_changers, &changer.path) {
130 entry.vendor = Some(info.vendor.clone());
131 entry.model = Some(info.model.clone());
132 entry.serial = Some(info.serial.clone());
133 }
134
135 list.push(entry);
136 }
137
138 rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
139 Ok(list)
140}
141
142#[api(
314652a4 143 protected: true,
50bf10ad
DM
144 input: {
145 properties: {
146 name: {
147 schema: CHANGER_ID_SCHEMA,
148 },
149 path: {
150 schema: LINUX_DRIVE_PATH_SCHEMA,
151 optional: true,
152 },
5ba83ed0
DM
153 digest: {
154 schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
155 optional: true,
156 },
157 },
50bf10ad
DM
158 },
159)]
160/// Update a tape changer configuration
161pub fn update_changer(
162 name: String,
163 path: Option<String>,
5ba83ed0 164 digest: Option<String>,
50bf10ad
DM
165 _param: Value,
166) -> Result<(), Error> {
167
168 let _lock = config::drive::lock()?;
169
5ba83ed0
DM
170 let (mut config, expected_digest) = config::drive::config()?;
171
172 if let Some(ref digest) = digest {
173 let digest = proxmox::tools::hex_to_digest(digest)?;
174 crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
175 }
50bf10ad
DM
176
177 let mut data: ScsiTapeChanger = config.lookup("changer", &name)?;
178
179 if let Some(path) = path {
180 let changers = linux_tape_changer_list();
181 check_drive_path(&changers, &path)?;
182 data.path = path;
183 }
184
185 config.set_data(&name, "changer", &data)?;
186
187 config::drive::save_config(&config)?;
188
189 Ok(())
190}
191
192#[api(
314652a4 193 protected: true,
50bf10ad
DM
194 input: {
195 properties: {
196 name: {
197 schema: CHANGER_ID_SCHEMA,
198 },
199 },
200 },
201)]
202/// Delete a tape changer configuration
203pub fn delete_changer(name: String, _param: Value) -> Result<(), Error> {
204
205 let _lock = config::drive::lock()?;
206
207 let (mut config, _digest) = config::drive::config()?;
208
209 match config.sections.get(&name) {
210 Some((section_type, _)) => {
211 if section_type != "changer" {
212 bail!("Entry '{}' exists, but is not a changer device", name);
213 }
214 config.sections.remove(&name);
215 },
216 None => bail!("Delete changer '{}' failed - no such entry", name),
217 }
218
219 config::drive::save_config(&config)?;
220
221 Ok(())
222}
223
50bf10ad
DM
224const ITEM_ROUTER: Router = Router::new()
225 .get(&API_METHOD_GET_CONFIG)
226 .put(&API_METHOD_UPDATE_CHANGER)
227 .delete(&API_METHOD_DELETE_CHANGER);
228
229
230pub const ROUTER: Router = Router::new()
231 .get(&API_METHOD_LIST_CHANGERS)
232 .post(&API_METHOD_CREATE_CHANGER)
233 .match_all("name", &ITEM_ROUTER);