tape: sg-tape-cmd - add more ways to specify devices
This commit is contained in:
		@ -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(¶m)?;
 | 
				
			||||||
        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(¶m)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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(¶m)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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(¶m)?;
 | 
				
			||||||
        handle.volume_statistics()
 | 
					        handle.volume_statistics()
 | 
				
			||||||
    }).map_err(|err: Error| err.to_string());
 | 
					    }).map_err(|err: Error| err.to_string());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -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)?;
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user