fn generator_maybe_err()

in metalos/metalctl/src/generator.rs [266:361]


fn generator_maybe_err(cmdline: MetalosCmdline, log: Logger, opts: Opts) -> Result<BootMode> {
    let boot_mode = detect_mode(&cmdline).context("failed to detect boot mode")?;
    info!(log, "Booting with mode: {:?}", boot_mode);

    // use the mac address in the kernel command line, otherwise try to infer it
    // using crate::net_utils::get_mac()
    let mac_address: Option<String> = match cmdline.mac_address {
        Some(mac) => Some(mac),
        None => match get_mac() {
            Ok(m) => Some(m),
            Err(error) => {
                error!(log, "Skipping network dropin. Error was: {}", error);
                None
            }
        },
    };

    match &boot_mode {
        BootMode::MetalOSExisting => {
            let boot_info_result = metalos_existing_boot_info(
                cmdline.root,
                cmdline
                    .host_config_uri
                    .context("host-config-uri must be provided for metalos boots")?,
                mac_address,
            )
            .context("Failed to build normal metalos info")?;

            materialize_boot_info(
                log,
                &opts.normal_dir,
                &opts.environment_dir,
                &opts.network_unit_dir,
                boot_info_result.env,
                boot_info_result.extra_deps,
                boot_info_result.mount_unit,
                boot_info_result.network_unit_dropin,
            )
        }
        BootMode::MetalOSReimage => {
            let boot_info_result = metalos_reimage_boot_info(
                cmdline.root,
                cmdline
                    .host_config_uri
                    .context("host-config-uri must be provided for metalos boots")?,
                cmdline
                    .root_disk_package
                    .context("Root disk package must be provided for metalos reimage boots")?,
                mac_address,
            )
            .context("Failed to build normal metalos info")?;

            materialize_boot_info(
                log,
                &opts.normal_dir,
                &opts.environment_dir,
                &opts.network_unit_dir,
                boot_info_result.env,
                boot_info_result.extra_deps,
                boot_info_result.mount_unit,
                boot_info_result.network_unit_dropin,
            )
        }
        BootMode::Legacy => {
            let boot_info_result = legacy_boot_info(cmdline.root, mac_address)
                .context("failed to build legacy info")?;

            materialize_boot_info(
                log,
                &opts.normal_dir,
                &opts.environment_dir,
                &opts.network_unit_dir,
                boot_info_result.env,
                boot_info_result.extra_deps,
                boot_info_result.mount_unit,
                boot_info_result.network_unit_dropin,
            )
        }
    }
    .context("Failed to materialize_boot_info")?;

    // IMPORTANT: this MUST be the last thing that the generator does, otherwise
    // any bugs in the generator can be masked and cause future hard-to-diagnose
    // failures
    let default_target_path = opts.early_dir.join("default.target");
    match std::fs::remove_file(&default_target_path) {
        // NotFound error is Ok, others are not
        Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(()),
        x => x,
    }
    .context("while removing original default.target")?;
    symlink("/usr/lib/systemd/system/initrd.target", default_target_path)
        .context("while changing default target to initrd.target")?;

    Ok(boot_mode)
}