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,
|
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 {
|
if !msg.keep_files {
|
||||||
log::info!("Delete storage associated with the domain");
|
log::info!("Delete storage associated with the domain");
|
||||||
let path = AppConfig::get().vm_storage_path(msg.id);
|
let path = AppConfig::get().vm_storage_path(msg.id);
|
||||||
|
@ -250,6 +250,19 @@ impl AppConfig {
|
|||||||
self.storage_path().join("iso")
|
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
|
/// Get disk images storage directory
|
||||||
pub fn disk_images_storage_path(&self) -> PathBuf {
|
pub fn disk_images_storage_path(&self) -> PathBuf {
|
||||||
self.storage_path().join("disk_images")
|
self.storage_path().join("disk_images")
|
||||||
|
@ -57,6 +57,9 @@ pub const DISK_SIZE_MIN: FileSize = FileSize::from_mb(50);
|
|||||||
/// Disk size max (B)
|
/// Disk size max (B)
|
||||||
pub const DISK_SIZE_MAX: FileSize = FileSize::from_gb(20000);
|
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
|
/// Net nat entry comment max size
|
||||||
pub const NET_NAT_COMMENT_MAX_SIZE: usize = 250;
|
pub const NET_NAT_COMMENT_MAX_SIZE: usize = 250;
|
||||||
|
|
||||||
|
@ -142,9 +142,22 @@ impl VMInfo {
|
|||||||
return Err(StructureExtraction("Invalid number of vCPU specified!").into());
|
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 {
|
for iso_file in &self.iso_files {
|
||||||
if !files_utils::check_file_name(iso_file) {
|
if !files_utils::check_file_name(iso_file) {
|
||||||
return Err(StructureExtraction("ISO filename is invalid!").into());
|
return Err(StructureExtraction("ISO filename is invalid!").into());
|
||||||
@ -156,6 +169,13 @@ impl VMInfo {
|
|||||||
return Err(StructureExtraction("Specified ISO file does not exists!").into());
|
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 {
|
disks.push(DiskXML {
|
||||||
r#type: "file".to_string(),
|
r#type: "file".to_string(),
|
||||||
device: "cdrom".to_string(),
|
device: "cdrom".to_string(),
|
||||||
@ -165,7 +185,7 @@ impl VMInfo {
|
|||||||
cache: "none".to_string(),
|
cache: "none".to_string(),
|
||||||
},
|
},
|
||||||
source: DiskSourceXML {
|
source: DiskSourceXML {
|
||||||
file: path.to_string_lossy().to_string(),
|
file: iso_path.to_string_lossy().to_string(),
|
||||||
},
|
},
|
||||||
target: DiskTargetXML {
|
target: DiskTargetXML {
|
||||||
dev: format!(
|
dev: format!(
|
||||||
@ -182,6 +202,7 @@ impl VMInfo {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configure VNC access, if requested
|
||||||
let (vnc_graphics, vnc_video) = match self.vnc_access {
|
let (vnc_graphics, vnc_video) = match self.vnc_access {
|
||||||
true => (
|
true => (
|
||||||
Some(GraphicsXML {
|
Some(GraphicsXML {
|
||||||
@ -495,6 +516,7 @@ impl VMInfo {
|
|||||||
.iter()
|
.iter()
|
||||||
.filter(|d| d.device == "cdrom")
|
.filter(|d| d.device == "cdrom")
|
||||||
.map(|d| d.source.file.rsplit_once('/').unwrap().1.to_string())
|
.map(|d| d.source.file.rsplit_once('/').unwrap().1.to_string())
|
||||||
|
.filter(|d| !d.starts_with(constants::CLOUD_INIT_IMAGE_PREFIX_NAME))
|
||||||
.collect(),
|
.collect(),
|
||||||
|
|
||||||
file_disks: domain
|
file_disks: domain
|
||||||
|
@ -61,6 +61,8 @@ async fn main() -> std::io::Result<()> {
|
|||||||
|
|
||||||
log::debug!("Create required directory, if missing");
|
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().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().disk_images_storage_path()).unwrap();
|
||||||
files_utils::create_directory_if_missing(AppConfig::get().vnc_sockets_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();
|
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
|
/// cloud-localds source code: https://github.com/canonical/cloud-utils/blob/main/bin/cloud-localds
|
||||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Default)]
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Default)]
|
||||||
pub struct CloudInitConfig {
|
pub struct CloudInitConfig {
|
||||||
attach_config: bool,
|
pub attach_config: bool,
|
||||||
/// Main user data
|
/// Main user data
|
||||||
user_data: String,
|
pub user_data: String,
|
||||||
/// Instance ID, set in metadata file
|
/// Instance ID, set in metadata file
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
instance_id: Option<String>,
|
pub instance_id: Option<String>,
|
||||||
/// Local hostname, set in metadata file
|
/// Local hostname, set in metadata file
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
local_hostname: Option<String>,
|
pub local_hostname: Option<String>,
|
||||||
/// Network configuration
|
/// Network configuration
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
network_configuration: Option<String>,
|
pub network_configuration: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CloudInitConfig {
|
impl CloudInitConfig {
|
||||||
|
Reference in New Issue
Block a user