tape: implement destroy_media
This commit is contained in:
parent
fba0b77469
commit
fb657d8ee5
@ -1,9 +1,11 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::{bail, format_err, Error};
|
||||||
|
|
||||||
use proxmox::api::{api, Router, SubdirMap};
|
use proxmox::{
|
||||||
use proxmox::list_subdirs_api_method;
|
api::{api, Router, SubdirMap},
|
||||||
|
list_subdirs_api_method,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{
|
config::{
|
||||||
@ -11,6 +13,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
api2::types::{
|
api2::types::{
|
||||||
MEDIA_POOL_NAME_SCHEMA,
|
MEDIA_POOL_NAME_SCHEMA,
|
||||||
|
MEDIA_LABEL_SCHEMA,
|
||||||
MediaPoolConfig,
|
MediaPoolConfig,
|
||||||
MediaListEntry,
|
MediaListEntry,
|
||||||
MediaStatus,
|
MediaStatus,
|
||||||
@ -154,7 +157,57 @@ pub async fn list_media(pool: Option<String>) -> Result<Vec<MediaListEntry>, Err
|
|||||||
Ok(list)
|
Ok(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
input: {
|
||||||
|
properties: {
|
||||||
|
"changer-id": {
|
||||||
|
schema: MEDIA_LABEL_SCHEMA,
|
||||||
|
},
|
||||||
|
force: {
|
||||||
|
description: "Force removal (even if media is used in a media set).",
|
||||||
|
type: bool,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// Destroy media (completely remove from database)
|
||||||
|
pub fn destroy_media(changer_id: String, force: Option<bool>,) -> Result<(), Error> {
|
||||||
|
|
||||||
|
let force = force.unwrap_or(false);
|
||||||
|
|
||||||
|
let status_path = Path::new(TAPE_STATUS_DIR);
|
||||||
|
let mut inventory = Inventory::load(status_path)?;
|
||||||
|
|
||||||
|
let media_id = inventory.find_media_by_changer_id(&changer_id)
|
||||||
|
.ok_or_else(|| format_err!("no such media '{}'", changer_id))?;
|
||||||
|
|
||||||
|
if !force {
|
||||||
|
if let Some(ref set) = media_id.media_set_label {
|
||||||
|
let is_empty = set.uuid.as_ref() == [0u8;16];
|
||||||
|
if !is_empty {
|
||||||
|
bail!("media '{}' contains data (please use 'force' flag to remove.", changer_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let uuid = media_id.label.uuid.clone();
|
||||||
|
drop(media_id);
|
||||||
|
|
||||||
|
inventory.remove_media(&uuid)?;
|
||||||
|
|
||||||
|
let mut state_db = MediaStateDatabase::load(status_path)?;
|
||||||
|
state_db.remove_media(&uuid)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
const SUBDIRS: SubdirMap = &[
|
const SUBDIRS: SubdirMap = &[
|
||||||
|
(
|
||||||
|
"destroy",
|
||||||
|
&Router::new()
|
||||||
|
.get(&API_METHOD_DESTROY_MEDIA)
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"list",
|
"list",
|
||||||
&Router::new()
|
&Router::new()
|
||||||
|
@ -20,6 +20,7 @@ use proxmox_backup::{
|
|||||||
MediaListEntry,
|
MediaListEntry,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
tape::complete_media_changer_id,
|
||||||
config::{
|
config::{
|
||||||
media_pool::complete_pool_name,
|
media_pool::complete_pool_name,
|
||||||
},
|
},
|
||||||
@ -33,6 +34,12 @@ pub fn media_commands() -> CommandLineInterface {
|
|||||||
CliCommand::new(&API_METHOD_LIST_MEDIA)
|
CliCommand::new(&API_METHOD_LIST_MEDIA)
|
||||||
.completion_cb("pool", complete_pool_name)
|
.completion_cb("pool", complete_pool_name)
|
||||||
)
|
)
|
||||||
|
.insert(
|
||||||
|
"destroy-media",
|
||||||
|
CliCommand::new(&api2::tape::media::API_METHOD_DESTROY_MEDIA)
|
||||||
|
.arg_param(&["changer-id"])
|
||||||
|
.completion_cb("changer-id", complete_media_changer_id)
|
||||||
|
)
|
||||||
;
|
;
|
||||||
|
|
||||||
cmd_def.into()
|
cmd_def.into()
|
||||||
|
@ -251,6 +251,16 @@ impl Inventory {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove a single media persistently
|
||||||
|
pub fn remove_media(&mut self, uuid: &Uuid) -> Result<(), Error> {
|
||||||
|
let _lock = self.lock()?;
|
||||||
|
self.map = Self::load_media_db(&self.inventory_path)?;
|
||||||
|
self.map.remove(uuid);
|
||||||
|
self.update_helpers();
|
||||||
|
self.replace_file()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Lookup media
|
/// Lookup media
|
||||||
pub fn lookup_media(&self, uuid: &Uuid) -> Option<&MediaId> {
|
pub fn lookup_media(&self, uuid: &Uuid) -> Option<&MediaId> {
|
||||||
self.map.get(uuid)
|
self.map.get(uuid)
|
||||||
|
@ -201,6 +201,14 @@ impl MediaStateDatabase {
|
|||||||
self.store()
|
self.store()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Lock database, reload database, remove media, store database
|
||||||
|
pub fn remove_media(&mut self, uuid: &Uuid) -> Result<(), Error> {
|
||||||
|
let _lock = self.lock()?;
|
||||||
|
self.map = Self::load_media_db(&self.database_path)?;
|
||||||
|
self.map.remove(uuid);
|
||||||
|
self.store()
|
||||||
|
}
|
||||||
|
|
||||||
fn store(&self) -> Result<(), Error> {
|
fn store(&self) -> Result<(), Error> {
|
||||||
|
|
||||||
let mut list = Vec::new();
|
let mut list = Vec::new();
|
||||||
|
Loading…
Reference in New Issue
Block a user