tape: implement MediaPool flag to consider offline media
For standalone tape drives.
This commit is contained in:
		@ -109,9 +109,11 @@ fn backup_worker(
 | 
				
			|||||||
    let _lock = MediaPool::lock(status_path, &pool_config.name)?;
 | 
					    let _lock = MediaPool::lock(status_path, &pool_config.name)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    worker.log("update media online status");
 | 
					    worker.log("update media online status");
 | 
				
			||||||
    update_media_online_status(&pool_config.drive)?;
 | 
					    let has_changer = update_media_online_status(&pool_config.drive)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let pool = MediaPool::with_config(status_path, &pool_config)?;
 | 
					    let use_offline_media = !has_changer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let pool = MediaPool::with_config(status_path, &pool_config, use_offline_media)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut pool_writer = PoolWriter::new(pool, &pool_config.drive)?;
 | 
					    let mut pool_writer = PoolWriter::new(pool, &pool_config.drive)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -138,12 +140,16 @@ fn backup_worker(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Try to update the the media online status
 | 
					// Try to update the the media online status
 | 
				
			||||||
fn update_media_online_status(drive: &str) -> Result<(), Error> {
 | 
					fn update_media_online_status(drive: &str) -> Result<bool, Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (config, _digest) = config::drive::config()?;
 | 
					    let (config, _digest) = config::drive::config()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut has_changer = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if let Ok(Some((changer, changer_name))) = media_changer(&config, drive) {
 | 
					    if let Ok(Some((changer, changer_name))) = media_changer(&config, drive) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        has_changer = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let changer_id_list = changer.list_media_changer_ids()?;
 | 
					        let changer_id_list = changer.list_media_changer_ids()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let status_path = Path::new(TAPE_STATUS_DIR);
 | 
					        let status_path = Path::new(TAPE_STATUS_DIR);
 | 
				
			||||||
@ -159,7 +165,7 @@ fn update_media_online_status(drive: &str) -> Result<(), Error> {
 | 
				
			|||||||
        )?;
 | 
					        )?;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(())
 | 
					    Ok(has_changer)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn backup_snapshot(
 | 
					pub fn backup_snapshot(
 | 
				
			||||||
 | 
				
			|||||||
@ -81,7 +81,8 @@ pub async fn list_media(pool: Option<String>) -> Result<Vec<MediaListEntry>, Err
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        let config: MediaPoolConfig = config.lookup("pool", pool_name)?;
 | 
					        let config: MediaPoolConfig = config.lookup("pool", pool_name)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let pool = MediaPool::with_config(status_path, &config)?;
 | 
					        let use_offline_media = true; // does not matter here
 | 
				
			||||||
 | 
					        let pool = MediaPool::with_config(status_path, &config, use_offline_media)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let current_time = proxmox::tools::time::epoch_i64();
 | 
					        let current_time = proxmox::tools::time::epoch_i64();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -44,6 +44,7 @@ pub struct MediaPool {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    media_set_policy: MediaSetPolicy,
 | 
					    media_set_policy: MediaSetPolicy,
 | 
				
			||||||
    retention: RetentionPolicy,
 | 
					    retention: RetentionPolicy,
 | 
				
			||||||
 | 
					    use_offline_media: bool,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inventory: Inventory,
 | 
					    inventory: Inventory,
 | 
				
			||||||
    state_db: MediaStateDatabase,
 | 
					    state_db: MediaStateDatabase,
 | 
				
			||||||
@ -59,6 +60,7 @@ impl MediaPool {
 | 
				
			|||||||
        state_path: &Path,
 | 
					        state_path: &Path,
 | 
				
			||||||
        media_set_policy: MediaSetPolicy,
 | 
					        media_set_policy: MediaSetPolicy,
 | 
				
			||||||
        retention: RetentionPolicy,
 | 
					        retention: RetentionPolicy,
 | 
				
			||||||
 | 
					        use_offline_media: bool,
 | 
				
			||||||
     ) -> Result<Self, Error> {
 | 
					     ) -> Result<Self, Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let inventory = Inventory::load(state_path)?;
 | 
					        let inventory = Inventory::load(state_path)?;
 | 
				
			||||||
@ -74,6 +76,7 @@ impl MediaPool {
 | 
				
			|||||||
            name: String::from(name),
 | 
					            name: String::from(name),
 | 
				
			||||||
            media_set_policy,
 | 
					            media_set_policy,
 | 
				
			||||||
            retention,
 | 
					            retention,
 | 
				
			||||||
 | 
					            use_offline_media,
 | 
				
			||||||
            inventory,
 | 
					            inventory,
 | 
				
			||||||
            state_db,
 | 
					            state_db,
 | 
				
			||||||
            current_media_set,
 | 
					            current_media_set,
 | 
				
			||||||
@ -84,13 +87,14 @@ impl MediaPool {
 | 
				
			|||||||
    pub fn with_config(
 | 
					    pub fn with_config(
 | 
				
			||||||
        state_path: &Path,
 | 
					        state_path: &Path,
 | 
				
			||||||
        config: &MediaPoolConfig,
 | 
					        config: &MediaPoolConfig,
 | 
				
			||||||
 | 
					        use_offline_media: bool,
 | 
				
			||||||
    ) -> Result<Self, Error> {
 | 
					    ) -> Result<Self, Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let allocation = config.allocation.clone().unwrap_or(String::from("continue")).parse()?;
 | 
					        let allocation = config.allocation.clone().unwrap_or(String::from("continue")).parse()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let retention = config.retention.clone().unwrap_or(String::from("keep")).parse()?;
 | 
					        let retention = config.retention.clone().unwrap_or(String::from("keep")).parse()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MediaPool::new(&config.name, state_path, allocation, retention)
 | 
					        MediaPool::new(&config.name, state_path, allocation, retention, use_offline_media)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Returns the pool name
 | 
					    /// Returns the pool name
 | 
				
			||||||
@ -272,7 +276,14 @@ impl MediaPool {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // check if media is on site
 | 
					            // check if media is on site
 | 
				
			||||||
            match media.location() {
 | 
					            match media.location() {
 | 
				
			||||||
                MediaLocation::Online(_) | MediaLocation::Offline => { /* OK */ },
 | 
					                MediaLocation::Online(_) => { /* OK */ },
 | 
				
			||||||
 | 
					                MediaLocation::Offline => {
 | 
				
			||||||
 | 
					                    if self.use_offline_media {
 | 
				
			||||||
 | 
					                        /* OK */
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        continue;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
                MediaLocation::Vault(_) => continue,
 | 
					                MediaLocation::Vault(_) => continue,
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -380,9 +391,15 @@ impl MediaPool {
 | 
				
			|||||||
            match media.status() {
 | 
					            match media.status() {
 | 
				
			||||||
                MediaStatus::Full => { /* OK */ },
 | 
					                MediaStatus::Full => { /* OK */ },
 | 
				
			||||||
                MediaStatus::Writable if (seq + 1) == media_count =>  {
 | 
					                MediaStatus::Writable if (seq + 1) == media_count =>  {
 | 
				
			||||||
                    last_is_writable = true;
 | 
					 | 
				
			||||||
                    match media.location() {
 | 
					                    match media.location() {
 | 
				
			||||||
                        MediaLocation::Online(_) | MediaLocation::Offline => { /* OK */ },
 | 
					                        MediaLocation::Online(_) => {
 | 
				
			||||||
 | 
					                            last_is_writable = true;
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                        MediaLocation::Offline => {
 | 
				
			||||||
 | 
					                            if self.use_offline_media {
 | 
				
			||||||
 | 
					                                last_is_writable = true;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                        MediaLocation::Vault(vault) => {
 | 
					                        MediaLocation::Vault(vault) => {
 | 
				
			||||||
                            bail!("writable media offsite in vault '{}'", vault);
 | 
					                            bail!("writable media offsite in vault '{}'", vault);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user