Automatically generate cloud disk image when updating domains configuration
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			This commit is contained in:
		@@ -182,6 +182,13 @@ impl Handler<DeleteDomainReq> for LibVirtActor {
 | 
			
		||||
            false => sys::VIR_DOMAIN_UNDEFINE_NVRAM,
 | 
			
		||||
        })?;
 | 
			
		||||
 | 
			
		||||
        // Delete associated cloud init disk
 | 
			
		||||
        let cloud_init_disk = AppConfig::get().cloud_init_disk_path_for_vm(&domain_name);
 | 
			
		||||
        if cloud_init_disk.exists() {
 | 
			
		||||
            std::fs::remove_file(cloud_init_disk)?;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If requested, delete block storage associated with the VM
 | 
			
		||||
        if !msg.keep_files {
 | 
			
		||||
            log::info!("Delete storage associated with the domain");
 | 
			
		||||
            let path = AppConfig::get().vm_storage_path(msg.id);
 | 
			
		||||
 
 | 
			
		||||
@@ -250,6 +250,19 @@ impl AppConfig {
 | 
			
		||||
        self.storage_path().join("iso")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Get the path where generated cloud init disk image are stored
 | 
			
		||||
    pub fn cloud_init_disk_storage_path(&self) -> PathBuf {
 | 
			
		||||
        self.storage_path().join("cloud_init_disks")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Get the path where the disk image of a VM is stored
 | 
			
		||||
    pub fn cloud_init_disk_path_for_vm(&self, name: &str) -> PathBuf {
 | 
			
		||||
        self.cloud_init_disk_storage_path().join(format!(
 | 
			
		||||
            "{}-{name}.iso",
 | 
			
		||||
            constants::CLOUD_INIT_IMAGE_PREFIX_NAME
 | 
			
		||||
        ))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Get disk images storage directory
 | 
			
		||||
    pub fn disk_images_storage_path(&self) -> PathBuf {
 | 
			
		||||
        self.storage_path().join("disk_images")
 | 
			
		||||
 
 | 
			
		||||
@@ -57,6 +57,9 @@ pub const DISK_SIZE_MIN: FileSize = FileSize::from_mb(50);
 | 
			
		||||
/// Disk size max (B)
 | 
			
		||||
pub const DISK_SIZE_MAX: FileSize = FileSize::from_gb(20000);
 | 
			
		||||
 | 
			
		||||
/// Cloud init generated disk image prefix
 | 
			
		||||
pub const CLOUD_INIT_IMAGE_PREFIX_NAME: &str = "virtweb-cloudinit-autogen-image";
 | 
			
		||||
 | 
			
		||||
/// Net nat entry comment max size
 | 
			
		||||
pub const NET_NAT_COMMENT_MAX_SIZE: usize = 250;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -142,9 +142,22 @@ impl VMInfo {
 | 
			
		||||
            return Err(StructureExtraction("Invalid number of vCPU specified!").into());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let mut disks = vec![];
 | 
			
		||||
        let mut iso_absolute_files = vec![];
 | 
			
		||||
 | 
			
		||||
        // Add ISO files
 | 
			
		||||
        // Process cloud init image
 | 
			
		||||
        if self.cloud_init.attach_config {
 | 
			
		||||
            let cloud_init_disk_path = AppConfig::get().cloud_init_disk_path_for_vm(&self.name);
 | 
			
		||||
 | 
			
		||||
            // Apply latest cloud init configuration
 | 
			
		||||
            std::fs::write(
 | 
			
		||||
                &cloud_init_disk_path,
 | 
			
		||||
                self.cloud_init.generate_nocloud_disk()?,
 | 
			
		||||
            )?;
 | 
			
		||||
 | 
			
		||||
            iso_absolute_files.push(cloud_init_disk_path);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Process uploaded ISO files
 | 
			
		||||
        for iso_file in &self.iso_files {
 | 
			
		||||
            if !files_utils::check_file_name(iso_file) {
 | 
			
		||||
                return Err(StructureExtraction("ISO filename is invalid!").into());
 | 
			
		||||
@@ -156,6 +169,13 @@ impl VMInfo {
 | 
			
		||||
                return Err(StructureExtraction("Specified ISO file does not exists!").into());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            iso_absolute_files.push(path);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let mut disks = vec![];
 | 
			
		||||
 | 
			
		||||
        // Add ISO disk files
 | 
			
		||||
        for iso_path in iso_absolute_files {
 | 
			
		||||
            disks.push(DiskXML {
 | 
			
		||||
                r#type: "file".to_string(),
 | 
			
		||||
                device: "cdrom".to_string(),
 | 
			
		||||
@@ -165,7 +185,7 @@ impl VMInfo {
 | 
			
		||||
                    cache: "none".to_string(),
 | 
			
		||||
                },
 | 
			
		||||
                source: DiskSourceXML {
 | 
			
		||||
                    file: path.to_string_lossy().to_string(),
 | 
			
		||||
                    file: iso_path.to_string_lossy().to_string(),
 | 
			
		||||
                },
 | 
			
		||||
                target: DiskTargetXML {
 | 
			
		||||
                    dev: format!(
 | 
			
		||||
@@ -182,6 +202,7 @@ impl VMInfo {
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Configure VNC access, if requested
 | 
			
		||||
        let (vnc_graphics, vnc_video) = match self.vnc_access {
 | 
			
		||||
            true => (
 | 
			
		||||
                Some(GraphicsXML {
 | 
			
		||||
@@ -495,6 +516,7 @@ impl VMInfo {
 | 
			
		||||
                .iter()
 | 
			
		||||
                .filter(|d| d.device == "cdrom")
 | 
			
		||||
                .map(|d| d.source.file.rsplit_once('/').unwrap().1.to_string())
 | 
			
		||||
                .filter(|d| !d.starts_with(constants::CLOUD_INIT_IMAGE_PREFIX_NAME))
 | 
			
		||||
                .collect(),
 | 
			
		||||
 | 
			
		||||
            file_disks: domain
 | 
			
		||||
 
 | 
			
		||||
@@ -61,6 +61,8 @@ async fn main() -> std::io::Result<()> {
 | 
			
		||||
 | 
			
		||||
    log::debug!("Create required directory, if missing");
 | 
			
		||||
    files_utils::create_directory_if_missing(AppConfig::get().iso_storage_path()).unwrap();
 | 
			
		||||
    files_utils::create_directory_if_missing(AppConfig::get().cloud_init_disk_storage_path())
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    files_utils::create_directory_if_missing(AppConfig::get().disk_images_storage_path()).unwrap();
 | 
			
		||||
    files_utils::create_directory_if_missing(AppConfig::get().vnc_sockets_path()).unwrap();
 | 
			
		||||
    files_utils::set_file_permission(AppConfig::get().vnc_sockets_path(), 0o777).unwrap();
 | 
			
		||||
 
 | 
			
		||||
@@ -8,18 +8,18 @@ use std::process::Command;
 | 
			
		||||
/// cloud-localds source code: https://github.com/canonical/cloud-utils/blob/main/bin/cloud-localds
 | 
			
		||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Default)]
 | 
			
		||||
pub struct CloudInitConfig {
 | 
			
		||||
    attach_config: bool,
 | 
			
		||||
    pub attach_config: bool,
 | 
			
		||||
    /// Main user data
 | 
			
		||||
    user_data: String,
 | 
			
		||||
    pub user_data: String,
 | 
			
		||||
    /// Instance ID, set in metadata file
 | 
			
		||||
    #[serde(skip_serializing_if = "Option::is_none")]
 | 
			
		||||
    instance_id: Option<String>,
 | 
			
		||||
    pub instance_id: Option<String>,
 | 
			
		||||
    /// Local hostname, set in metadata file
 | 
			
		||||
    #[serde(skip_serializing_if = "Option::is_none")]
 | 
			
		||||
    local_hostname: Option<String>,
 | 
			
		||||
    pub local_hostname: Option<String>,
 | 
			
		||||
    /// Network configuration
 | 
			
		||||
    #[serde(skip_serializing_if = "Option::is_none")]
 | 
			
		||||
    network_configuration: Option<String>,
 | 
			
		||||
    pub network_configuration: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl CloudInitConfig {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user