]> git.proxmox.com Git - proxmox-backup.git/blob - src/bin/sg-tape-cmd.rs
tape: implement read_volume_statistics
[proxmox-backup.git] / src / bin / sg-tape-cmd.rs
1 /// Tape command implemented using scsi-generic raw commands
2 ///
3 /// SCSI-generic command needs root priviledges, so this binary need
4 /// to be setuid root.
5 ///
6 /// This command can use STDIN as tape device handle.
7
8 use std::fs::File;
9 use std::os::unix::io::{AsRawFd, FromRawFd};
10
11 use anyhow::{bail, Error};
12
13 use proxmox::{
14 api::{
15 api,
16 cli::*,
17 RpcEnvironment,
18 },
19 };
20
21 use proxmox_backup::{
22 api2::types::{
23 LINUX_DRIVE_PATH_SCHEMA,
24 },
25 tape::{
26 linux_tape::{
27 LinuxTapeHandle,
28 open_linux_tape_device,
29 check_tape_is_linux_tape_device,
30 },
31 },
32 };
33
34 fn get_tape_handle(device: Option<String>) -> Result<LinuxTapeHandle, Error> {
35
36 let file = if let Some(device) = device {
37 open_linux_tape_device(&device)?
38 } else {
39 let fd = std::io::stdin().as_raw_fd();
40 let file = unsafe { File::from_raw_fd(fd) };
41 check_tape_is_linux_tape_device(&file)?;
42 file
43 };
44 Ok(LinuxTapeHandle::new(file))
45 }
46
47 #[api(
48 input: {
49 properties: {
50 device: {
51 schema: LINUX_DRIVE_PATH_SCHEMA,
52 optional: true,
53 },
54 },
55 },
56 )]
57 /// Tape/Media Status
58 fn status(
59 device: Option<String>,
60 ) -> Result<(), Error> {
61
62 let result = proxmox::try_block!({
63 let mut handle = get_tape_handle(device)?;
64 handle.get_drive_and_media_status()
65 }).map_err(|err: Error| err.to_string());
66
67 println!("{}", serde_json::to_string_pretty(&result)?);
68
69 Ok(())
70 }
71
72 #[api(
73 input: {
74 properties: {
75 device: {
76 schema: LINUX_DRIVE_PATH_SCHEMA,
77 optional: true,
78 },
79 },
80 },
81 )]
82 /// Read Cartridge Memory (Medium auxiliary memory attributes)
83 fn cartridge_memory(
84 device: Option<String>,
85 ) -> Result<(), Error> {
86
87 let result = proxmox::try_block!({
88 let mut handle = get_tape_handle(device)?;
89
90 handle.cartridge_memory()
91 }).map_err(|err| err.to_string());
92
93 println!("{}", serde_json::to_string_pretty(&result)?);
94
95 Ok(())
96 }
97
98 #[api(
99 input: {
100 properties: {
101 device: {
102 schema: LINUX_DRIVE_PATH_SCHEMA,
103 optional: true,
104 },
105 },
106 },
107 )]
108 /// Read Tape Alert Flags
109 fn tape_alert_flags(
110 device: Option<String>,
111 ) -> Result<(), Error> {
112
113 let result = proxmox::try_block!({
114 let mut handle = get_tape_handle(device)?;
115
116 let flags = handle.tape_alert_flags()?;
117 Ok(flags.bits())
118 }).map_err(|err: Error| err.to_string());
119
120 println!("{}", serde_json::to_string_pretty(&result)?);
121
122 Ok(())
123 }
124
125 #[api(
126 input: {
127 properties: {
128 device: {
129 schema: LINUX_DRIVE_PATH_SCHEMA,
130 optional: true,
131 },
132 },
133 },
134 )]
135 /// Read volume statistics
136 fn volume_statistics(
137 device: Option<String>,
138 ) -> Result<(), Error> {
139
140 let result = proxmox::try_block!({
141 let mut handle = get_tape_handle(device)?;
142 handle.volume_statistics()
143 }).map_err(|err: Error| err.to_string());
144
145 println!("{}", serde_json::to_string_pretty(&result)?);
146
147 Ok(())
148 }
149
150 fn main() -> Result<(), Error> {
151
152 // check if we are user root or backup
153 let backup_uid = proxmox_backup::backup::backup_user()?.uid;
154 let backup_gid = proxmox_backup::backup::backup_group()?.gid;
155 let running_uid = nix::unistd::Uid::current();
156 let running_gid = nix::unistd::Gid::current();
157
158 let effective_uid = nix::unistd::Uid::effective();
159 if !effective_uid.is_root() {
160 bail!("this program needs to be run with setuid root");
161 }
162
163 if !running_uid.is_root() {
164 if running_uid != backup_uid || running_gid != backup_gid {
165 bail!(
166 "Not running as backup user or group (got uid {} gid {})",
167 running_uid, running_gid,
168 );
169 }
170 }
171
172 let cmd_def = CliCommandMap::new()
173 .insert(
174 "status",
175 CliCommand::new(&API_METHOD_STATUS)
176 )
177 .insert(
178 "cartridge-memory",
179 CliCommand::new(&API_METHOD_CARTRIDGE_MEMORY)
180 )
181 .insert(
182 "tape-alert-flags",
183 CliCommand::new(&API_METHOD_TAPE_ALERT_FLAGS)
184 )
185 .insert(
186 "volume-statistics",
187 CliCommand::new(&API_METHOD_VOLUME_STATISTICS)
188 )
189 ;
190
191 let mut rpcenv = CliEnvironment::new();
192 rpcenv.set_auth_id(Some(String::from("root@pam")));
193
194 run_cli_command(cmd_def, rpcenv, None);
195
196 Ok(())
197 }