tape: sg-tape-cmd - add more ways to specify devices

This commit is contained in:
Dietmar Maurer 2021-01-14 13:05:26 +01:00
parent 781da7f6f0
commit 2d50a6192f
2 changed files with 91 additions and 15 deletions

View File

@ -8,7 +8,8 @@
use std::fs::File; use std::fs::File;
use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::io::{AsRawFd, FromRawFd};
use anyhow::{bail, Error}; use anyhow::{bail, format_err, Error};
use serde_json::Value;
use proxmox::{ use proxmox::{
api::{ api::{
@ -19,8 +20,11 @@ use proxmox::{
}; };
use proxmox_backup::{ use proxmox_backup::{
config,
api2::types::{ api2::types::{
LINUX_DRIVE_PATH_SCHEMA, LINUX_DRIVE_PATH_SCHEMA,
DRIVE_NAME_SCHEMA,
LinuxTapeDrive,
}, },
tape::{ tape::{
TapeDriver, TapeDriver,
@ -32,36 +36,78 @@ use proxmox_backup::{
}, },
}; };
fn get_tape_handle(device: Option<String>) -> Result<LinuxTapeHandle, Error> { fn get_tape_handle(param: &Value) -> Result<LinuxTapeHandle, Error> {
let file = if let Some(device) = device { let handle = if let Some(name) = param["drive"].as_str() {
open_linux_tape_device(&device)? let (config, _digest) = config::drive::config()?;
} else { let drive: LinuxTapeDrive = config.lookup("linux", &name)?;
eprintln!("using device {}", drive.path);
drive.open()
.map_err(|err| format_err!("open drive '{}' ({}) failed - {}", name, drive.path, err))?
} else if let Some(device) = param["device"].as_str() {
eprintln!("using device {}", device);
LinuxTapeHandle::new(open_linux_tape_device(&device)?)
} else if let Some(true) = param["stdin"].as_bool() {
eprintln!("using stdin");
let fd = std::io::stdin().as_raw_fd(); let fd = std::io::stdin().as_raw_fd();
let file = unsafe { File::from_raw_fd(fd) }; let file = unsafe { File::from_raw_fd(fd) };
check_tape_is_linux_tape_device(&file)?; check_tape_is_linux_tape_device(&file)?;
file LinuxTapeHandle::new(file)
} else if let Some(name) = std::env::var("PROXMOX_TAPE_DRIVE").ok() {
let (config, _digest) = config::drive::config()?;
let drive: LinuxTapeDrive = config.lookup("linux", &name)?;
eprintln!("using device {}", drive.path);
drive.open()
.map_err(|err| format_err!("open drive '{}' ({}) failed - {}", name, drive.path, err))?
} else {
let (config, _digest) = config::drive::config()?;
let mut drive_names = Vec::new();
for (name, (section_type, _)) in config.sections.iter() {
if section_type != "linux" { continue; }
drive_names.push(name);
}
if drive_names.len() == 1 {
let name = drive_names[0];
let drive: LinuxTapeDrive = config.lookup("linux", &name)?;
eprintln!("using device {}", drive.path);
drive.open()
.map_err(|err| format_err!("open drive '{}' ({}) failed - {}", name, drive.path, err))?
} else {
bail!("no drive/device specified");
}
}; };
Ok(LinuxTapeHandle::new(file))
Ok(handle)
} }
#[api( #[api(
input: { input: {
properties: { properties: {
drive: {
schema: DRIVE_NAME_SCHEMA,
optional: true,
},
device: { device: {
schema: LINUX_DRIVE_PATH_SCHEMA, schema: LINUX_DRIVE_PATH_SCHEMA,
optional: true, optional: true,
}, },
stdin: {
description: "Use standard input as device handle.",
type: bool,
optional: true,
},
}, },
}, },
)] )]
/// Tape/Media Status /// Tape/Media Status
fn status( fn status(
device: Option<String>, param: Value,
) -> Result<(), Error> { ) -> Result<(), Error> {
let result = proxmox::try_block!({ let result = proxmox::try_block!({
let mut handle = get_tape_handle(device)?; let mut handle = get_tape_handle(&param)?;
handle.get_drive_and_media_status() handle.get_drive_and_media_status()
}).map_err(|err: Error| err.to_string()); }).map_err(|err: Error| err.to_string());
@ -73,20 +119,29 @@ fn status(
#[api( #[api(
input: { input: {
properties: { properties: {
drive: {
schema: DRIVE_NAME_SCHEMA,
optional: true,
},
device: { device: {
schema: LINUX_DRIVE_PATH_SCHEMA, schema: LINUX_DRIVE_PATH_SCHEMA,
optional: true, optional: true,
}, },
stdin: {
description: "Use standard input as device handle.",
type: bool,
optional: true,
},
}, },
}, },
)] )]
/// Read Cartridge Memory (Medium auxiliary memory attributes) /// Read Cartridge Memory (Medium auxiliary memory attributes)
fn cartridge_memory( fn cartridge_memory(
device: Option<String>, param: Value,
) -> Result<(), Error> { ) -> Result<(), Error> {
let result = proxmox::try_block!({ let result = proxmox::try_block!({
let mut handle = get_tape_handle(device)?; let mut handle = get_tape_handle(&param)?;
handle.cartridge_memory() handle.cartridge_memory()
}).map_err(|err| err.to_string()); }).map_err(|err| err.to_string());
@ -99,20 +154,29 @@ fn cartridge_memory(
#[api( #[api(
input: { input: {
properties: { properties: {
drive: {
schema: DRIVE_NAME_SCHEMA,
optional: true,
},
device: { device: {
schema: LINUX_DRIVE_PATH_SCHEMA, schema: LINUX_DRIVE_PATH_SCHEMA,
optional: true, optional: true,
}, },
stdin: {
description: "Use standard input as device handle.",
type: bool,
optional: true,
},
}, },
}, },
)] )]
/// Read Tape Alert Flags /// Read Tape Alert Flags
fn tape_alert_flags( fn tape_alert_flags(
device: Option<String>, param: Value,
) -> Result<(), Error> { ) -> Result<(), Error> {
let result = proxmox::try_block!({ let result = proxmox::try_block!({
let mut handle = get_tape_handle(device)?; let mut handle = get_tape_handle(&param)?;
let flags = handle.tape_alert_flags()?; let flags = handle.tape_alert_flags()?;
Ok(flags.bits()) Ok(flags.bits())
@ -126,20 +190,29 @@ fn tape_alert_flags(
#[api( #[api(
input: { input: {
properties: { properties: {
drive: {
schema: DRIVE_NAME_SCHEMA,
optional: true,
},
device: { device: {
schema: LINUX_DRIVE_PATH_SCHEMA, schema: LINUX_DRIVE_PATH_SCHEMA,
optional: true, optional: true,
}, },
stdin: {
description: "Use standard input as device handle.",
type: bool,
optional: true,
},
}, },
}, },
)] )]
/// Read volume statistics /// Read volume statistics
fn volume_statistics( fn volume_statistics(
device: Option<String>, param: Value,
) -> Result<(), Error> { ) -> Result<(), Error> {
let result = proxmox::try_block!({ let result = proxmox::try_block!({
let mut handle = get_tape_handle(device)?; let mut handle = get_tape_handle(&param)?;
handle.volume_statistics() handle.volume_statistics()
}).map_err(|err: Error| err.to_string()); }).map_err(|err: Error| err.to_string());

View File

@ -331,6 +331,7 @@ impl LinuxTapeHandle {
let mut command = std::process::Command::new( let mut command = std::process::Command::new(
"/usr/lib/x86_64-linux-gnu/proxmox-backup/sg-tape-cmd"); "/usr/lib/x86_64-linux-gnu/proxmox-backup/sg-tape-cmd");
command.args(&["cartridge-memory"]); command.args(&["cartridge-memory"]);
command.args(&["--stdin"]);
command.stdin(unsafe { std::process::Stdio::from_raw_fd(self.file.as_raw_fd())}); command.stdin(unsafe { std::process::Stdio::from_raw_fd(self.file.as_raw_fd())});
let output = run_command(command, None)?; let output = run_command(command, None)?;
let result: Result<Vec<MamAttribute>, String> = serde_json::from_str(&output)?; let result: Result<Vec<MamAttribute>, String> = serde_json::from_str(&output)?;
@ -350,6 +351,7 @@ impl LinuxTapeHandle {
let mut command = std::process::Command::new( let mut command = std::process::Command::new(
"/usr/lib/x86_64-linux-gnu/proxmox-backup/sg-tape-cmd"); "/usr/lib/x86_64-linux-gnu/proxmox-backup/sg-tape-cmd");
command.args(&["volume-statistics"]); command.args(&["volume-statistics"]);
command.args(&["--stdin"]);
command.stdin(unsafe { std::process::Stdio::from_raw_fd(self.file.as_raw_fd())}); command.stdin(unsafe { std::process::Stdio::from_raw_fd(self.file.as_raw_fd())});
let output = run_command(command, None)?; let output = run_command(command, None)?;
let result: Result<Lp17VolumeStatistics, String> = serde_json::from_str(&output)?; let result: Result<Lp17VolumeStatistics, String> = serde_json::from_str(&output)?;
@ -492,6 +494,7 @@ impl TapeDriver for LinuxTapeHandle {
let mut command = std::process::Command::new( let mut command = std::process::Command::new(
"/usr/lib/x86_64-linux-gnu/proxmox-backup/sg-tape-cmd"); "/usr/lib/x86_64-linux-gnu/proxmox-backup/sg-tape-cmd");
command.args(&["tape-alert-flags"]); command.args(&["tape-alert-flags"]);
command.args(&["--stdin"]);
command.stdin(unsafe { std::process::Stdio::from_raw_fd(self.file.as_raw_fd())}); command.stdin(unsafe { std::process::Stdio::from_raw_fd(self.file.as_raw_fd())});
let output = run_command(command, None)?; let output = run_command(command, None)?;
let result: Result<u64, String> = serde_json::from_str(&output)?; let result: Result<u64, String> = serde_json::from_str(&output)?;