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