2018-12-31 18:27:17 -05:00
|
|
|
|
2019-01-30 21:31:13 -05:00
|
|
|
use std::thread::{self,JoinHandle};
|
2018-12-31 18:27:17 -05:00
|
|
|
use std::time;
|
2019-01-30 21:31:13 -05:00
|
|
|
use std::path::Path;
|
2019-01-30 14:11:30 -05:00
|
|
|
use std::ffi::OsStr;
|
2019-01-30 21:31:13 -05:00
|
|
|
use std::fs;
|
2018-12-31 18:27:17 -05:00
|
|
|
|
2019-01-30 21:31:13 -05:00
|
|
|
use libcitadel::Result;
|
|
|
|
use libcitadel::util;
|
|
|
|
use libcitadel::ResourceImage;
|
|
|
|
use crate::boot::disks;
|
|
|
|
use crate::boot::rootfs::setup_rootfs_resource;
|
|
|
|
use crate::install::installer::Installer;
|
2018-12-31 18:27:17 -05:00
|
|
|
|
2019-01-30 21:31:13 -05:00
|
|
|
const IMAGE_DIRECTORY: &str = "/run/citadel/images";
|
2018-12-31 18:27:17 -05:00
|
|
|
|
2019-01-30 21:31:13 -05:00
|
|
|
pub fn live_rootfs() -> Result<()> {
|
|
|
|
copy_artifacts()?;
|
|
|
|
let rootfs = find_rootfs_image()?;
|
|
|
|
setup_rootfs_resource(&rootfs)
|
2018-12-31 18:27:17 -05:00
|
|
|
}
|
|
|
|
|
2019-01-30 21:31:13 -05:00
|
|
|
pub fn live_setup() -> Result<()> {
|
|
|
|
decompress_images()?;
|
|
|
|
let live = Installer::new_livesetup();
|
|
|
|
live.run()
|
2018-12-31 18:27:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn copy_artifacts() -> Result<()> {
|
|
|
|
for _ in 0..3 {
|
|
|
|
if try_copy_artifacts()? {
|
2019-01-30 21:31:13 -05:00
|
|
|
//decompress_images()?;
|
2018-12-31 18:27:17 -05:00
|
|
|
return Ok(())
|
|
|
|
}
|
|
|
|
// Try again after waiting for more devices to be discovered
|
2019-01-30 21:31:13 -05:00
|
|
|
info!("Failed to find partition with images, trying again in 2 seconds");
|
2018-12-31 18:27:17 -05:00
|
|
|
thread::sleep(time::Duration::from_secs(2));
|
|
|
|
}
|
|
|
|
Err(format_err!("Could not find partition containing resource images"))
|
2019-01-30 21:31:13 -05:00
|
|
|
|
2018-12-31 18:27:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn try_copy_artifacts() -> Result<bool> {
|
|
|
|
let rootfs_image = Path::new("/boot/images/citadel-rootfs.img");
|
|
|
|
// Already mounted?
|
|
|
|
if rootfs_image.exists() {
|
|
|
|
deploy_artifacts()?;
|
|
|
|
return Ok(true);
|
|
|
|
}
|
|
|
|
for part in disks::DiskPartition::boot_partitions()? {
|
|
|
|
part.mount("/boot")?;
|
|
|
|
|
|
|
|
if rootfs_image.exists() {
|
|
|
|
deploy_artifacts()?;
|
|
|
|
part.umount()?;
|
|
|
|
return Ok(true);
|
|
|
|
}
|
|
|
|
part.umount()?;
|
|
|
|
}
|
|
|
|
Ok(false)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn deploy_artifacts() -> Result<()> {
|
2019-01-30 21:31:13 -05:00
|
|
|
let run_images = Path::new(IMAGE_DIRECTORY);
|
2018-12-31 18:27:17 -05:00
|
|
|
if !run_images.exists() {
|
|
|
|
fs::create_dir_all(run_images)?;
|
2019-01-30 21:31:13 -05:00
|
|
|
util::exec_cmdline("/bin/mount", "-t tmpfs -o size=4g images /run/citadel/images")?;
|
2018-12-31 18:27:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
for entry in fs::read_dir("/boot/images")? {
|
|
|
|
let entry = entry?;
|
2019-01-30 21:31:13 -05:00
|
|
|
println!("Copying {:?} from /boot/images to /run/citadel/images", entry.file_name());
|
2018-12-31 18:27:17 -05:00
|
|
|
fs::copy(entry.path(), run_images.join(entry.file_name()))?;
|
|
|
|
}
|
2019-01-30 21:31:13 -05:00
|
|
|
println!("Copying bzImage to /run/citadel/images");
|
|
|
|
fs::copy("/boot/bzImage", "/run/citadel/images/bzImage")?;
|
2018-12-31 18:27:17 -05:00
|
|
|
|
2019-01-30 21:31:13 -05:00
|
|
|
println!("Copying bootx64.efi to /run/citadel/images");
|
|
|
|
fs::copy("/boot/EFI/BOOT/bootx64.efi", "/run/citadel/images/bootx64.efi")?;
|
2018-12-31 18:27:17 -05:00
|
|
|
|
|
|
|
deploy_syslinux_artifacts()?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn deploy_syslinux_artifacts() -> Result<()> {
|
|
|
|
let boot_syslinux = Path::new("/boot/syslinux");
|
|
|
|
|
|
|
|
if !boot_syslinux.exists() {
|
|
|
|
println!("Not copying syslinux components because /boot/syslinux does not exist");
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
2019-01-30 21:31:13 -05:00
|
|
|
println!("Copying contents of /boot/syslinux to /run/citadel/images/syslinux");
|
2018-12-31 18:27:17 -05:00
|
|
|
|
2019-01-30 21:31:13 -05:00
|
|
|
let run_images_syslinux = Path::new("/run/citadel/images/syslinux");
|
2018-12-31 18:27:17 -05:00
|
|
|
fs::create_dir_all(run_images_syslinux)?;
|
|
|
|
for entry in fs::read_dir(boot_syslinux)? {
|
|
|
|
let entry = entry?;
|
|
|
|
if let Some(ext) = entry.path().extension() {
|
|
|
|
if ext == "c32" || ext == "bin" {
|
|
|
|
fs::copy(entry.path(), run_images_syslinux.join(entry.file_name()))?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2019-01-30 21:31:13 -05:00
|
|
|
fn find_rootfs_image() -> Result<ResourceImage> {
|
|
|
|
for entry in fs::read_dir(IMAGE_DIRECTORY)? {
|
|
|
|
let entry = entry?;
|
|
|
|
if entry.path().extension() == Some(OsStr::new("img")) {
|
|
|
|
if let Ok(image) = ResourceImage::from_path(&entry.path()) {
|
|
|
|
if image.metainfo().image_type() == "rootfs" {
|
|
|
|
return Ok(image)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(format_err!("Unable to find rootfs resource image in {}", IMAGE_DIRECTORY))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-01-30 14:11:30 -05:00
|
|
|
fn decompress_images() -> Result<()> {
|
|
|
|
println!("decompressing images");
|
|
|
|
let mut threads = Vec::new();
|
2019-01-30 21:31:13 -05:00
|
|
|
for entry in fs::read_dir("/run/citadel/images")? {
|
2019-01-30 14:11:30 -05:00
|
|
|
let entry = entry?;
|
|
|
|
if entry.path().extension() == Some(OsStr::new("img")) {
|
|
|
|
if let Ok(image) = ResourceImage::from_path(&entry.path()) {
|
2019-01-30 21:31:13 -05:00
|
|
|
if image.is_compressed() {
|
|
|
|
threads.push(decompress_one_image(image));
|
|
|
|
}
|
2019-01-30 14:11:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for t in threads {
|
|
|
|
t.join().unwrap()?;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
fn decompress_one_image(image: ResourceImage) -> JoinHandle<Result<()>> {
|
|
|
|
thread::spawn(move ||{
|
|
|
|
image.decompress()
|
|
|
|
})
|
|
|
|
}
|