This patch switches the behavior to use the settings that can be
specified in the ISO.

This means, that it is possible to control how the answer file should be
fetched:

* auto - as usually, go through the options until one works (partition,
  http)
* included - the answer file is included in the ISO
* partition - only check for an answer file in a partition called
  'proxmoxinst' in lower or uppercase
* http - only fetch the answer file via an HTTP POST request.

Additionally it is possible to specify the HTTP URL directly in the ISO.

Placing the SSL fingerprint on a partition is not possible anymore. If
one wants to provide it right away (besides DHCP or DNS), it must be
incluced in the ISO itself. This reduced the need for another USB flash
drive.

Signed-off-by: Aaron Lauterer <a.laute...@proxmox.com>
---
 proxmox-fetch-answer/Cargo.toml               |  1 +
 .../src/fetch_plugins/http.rs                 | 65 +++++++------------
 proxmox-fetch-answer/src/main.rs              | 64 ++++++++++++++----
 3 files changed, 77 insertions(+), 53 deletions(-)

diff --git a/proxmox-fetch-answer/Cargo.toml b/proxmox-fetch-answer/Cargo.toml
index fbcca46..797c185 100644
--- a/proxmox-fetch-answer/Cargo.toml
+++ b/proxmox-fetch-answer/Cargo.toml
@@ -17,6 +17,7 @@ log = "0.4.20"
 ureq = { version = "2.6", features = [ "native-certs", "native-tls" ] }
 rustls = { version = "0.20", features = [ "dangerous_configuration" ] }
 rustls-native-certs = "0.6"
+toml = "0.7"
 native-tls = "0.2"
 sha2 = "0.10"
 hex = "0.4"
diff --git a/proxmox-fetch-answer/src/fetch_plugins/http.rs 
b/proxmox-fetch-answer/src/fetch_plugins/http.rs
index 5772c42..4093131 100644
--- a/proxmox-fetch-answer/src/fetch_plugins/http.rs
+++ b/proxmox-fetch-answer/src/fetch_plugins/http.rs
@@ -2,16 +2,12 @@ use anyhow::{bail, Error, Result};
 use log::info;
 use std::{
     fs::{self, read_to_string},
-    path::Path,
     process::Command,
 };
 
 use crate::fetch_plugins::utils::post;
-use proxmox_auto_installer::sysinfo;
+use proxmox_auto_installer::{sysinfo, utils::AutoInstSettings};
 
-use super::utils;
-
-static CERT_FINGERPRINT_FILE: &str = "cert_fingerprint.txt";
 static ANSWER_SUBDOMAIN: &str = "proxmoxinst";
 static ANSWER_SUBDOMAIN_FP: &str = "proxmoxinst-fp";
 
@@ -37,30 +33,33 @@ pub struct FetchFromHTTP;
 
 impl FetchFromHTTP {
     /// Will try to fetch the answer.toml by sending a HTTP POST request. The 
URL can be configured
-    /// either via DHCP or DNS.
-    /// DHCP options are checked first. The SSL certificate need to be either 
trusted by the root
-    /// certs or a SHA256 fingerprint needs to be provided. The SHA256 SSL 
fingerprint can either
-    /// be placed in a `cert_fingerprint.txt` file in the `proxmoxinst` 
partition, as DHCP option,
-    /// or as DNS TXT record. If provided, the `cert_fingerprint.txt` file has 
preference.
-    pub fn get_answer() -> Result<String> {
-        info!("Checking for certificate fingerprint in file.");
-        let mut fingerprint: Option<String> = match 
Self::get_cert_fingerprint_from_file() {
-            Ok(fp) => Some(fp),
-            Err(err) => {
-                info!("{err}");
-                None
+    /// either via DHCP or DNS or preconfigured in the ISO.
+    /// If the URL is not defined in the ISO, it will first check DHCP 
options. The SSL certificate
+    /// needs to be either trusted by the root certs or a SHA256 fingerprint 
needs to be provided.
+    /// The SHA256 SSL fingerprint can either be defined in the ISO, as DHCP 
option, or as DNS TXT
+    /// record. If provided, the fingerprint provided in the ISO has 
preference.
+    pub fn get_answer(settings: &AutoInstSettings) -> Result<String> {
+        let mut fingerprint: Option<String> = match 
settings.cert_fingerprint.clone() {
+            Some(fp) => {
+                info!("SSL fingerprint provided through ISO.");
+                Some(fp)
             }
+            None => None,
         };
 
         let answer_url: String;
-
-        (answer_url, fingerprint) = match 
Self::fetch_dhcp(fingerprint.clone()) {
-            Ok((url, fp)) => (url, fp),
-            Err(err) => {
-                info!("{err}");
-                Self::fetch_dns(fingerprint.clone())?
-            }
-        };
+        if let Some(url) = settings.http_url.clone() {
+            info!("URL specified in ISO");
+            answer_url = url;
+        } else {
+            (answer_url, fingerprint) = match 
Self::fetch_dhcp(fingerprint.clone()) {
+                Ok((url, fp)) => (url, fp),
+                Err(err) => {
+                    info!("{err}");
+                    Self::fetch_dns(fingerprint.clone())?
+                }
+            };
+        }
 
         if fingerprint.is_some() {
             let fp = fingerprint.clone();
@@ -74,22 +73,6 @@ impl FetchFromHTTP {
         Ok(answer)
     }
 
-    /// Reads certificate fingerprint from file
-    pub fn get_cert_fingerprint_from_file() -> Result<String> {
-        let mount_path = utils::mount_proxmoxinst_part()?;
-        let cert_path = 
Path::new(mount_path.as_str()).join(CERT_FINGERPRINT_FILE);
-        match cert_path.try_exists() {
-            Ok(true) => {
-                info!("Found certifacte fingerprint file.");
-                Ok(fs::read_to_string(cert_path)?.trim().into())
-            }
-            _ => Err(Error::msg(format!(
-                "could not find cert fingerprint file expected at: {}",
-                cert_path.display()
-            ))),
-        }
-    }
-
     /// Fetches search domain from resolv.conf file
     fn get_search_domain() -> Result<String> {
         info!("Retrieving default search domain.");
diff --git a/proxmox-fetch-answer/src/main.rs b/proxmox-fetch-answer/src/main.rs
index 8c762e9..fe5d599 100644
--- a/proxmox-fetch-answer/src/main.rs
+++ b/proxmox-fetch-answer/src/main.rs
@@ -1,13 +1,15 @@
 use anyhow::{anyhow, Error, Result};
 use fetch_plugins::{http::FetchFromHTTP, partition::FetchFromPartition};
 use log::{error, info, LevelFilter};
-use proxmox_auto_installer::log::AutoInstLogger;
+use proxmox_auto_installer::{log::AutoInstLogger, utils::{AutoInstModes, 
AutoInstSettings}};
+use std::{fs, path::PathBuf};
 use std::io::Write;
 use std::process::{Command, ExitCode, Stdio};
 
 mod fetch_plugins;
 
 static LOGGER: AutoInstLogger = AutoInstLogger;
+static AUTOINST_MODE_FILE: &str = "/cdrom/autoinst-mode.toml";
 
 pub fn init_log() -> Result<()> {
     AutoInstLogger::init("/tmp/fetch_answer.log")?;
@@ -16,16 +18,40 @@ pub fn init_log() -> Result<()> {
         .map_err(|err| anyhow!(err))
 }
 
-fn fetch_answer() -> Result<String> {
-    match FetchFromPartition::get_answer() {
-        Ok(answer) => return Ok(answer),
-        Err(err) => info!("Fetching answer file from partition failed: {err}"),
-    }
-    match FetchFromHTTP::get_answer() {
-        Ok(answer) => return Ok(answer),
-        Err(err) => info!("Fetching answer file via HTTP failed: {err}"),
-    }
+fn fetch_answer(install_settings: &AutoInstSettings) -> Result<String> {
+    info!("Fetching answer file in mode {:?}:", &install_settings.mode);
+    match install_settings.mode {
+        AutoInstModes::Auto => {
+            match FetchFromPartition::get_answer() {
+                Ok(answer) => return Ok(answer),
+                Err(err) => info!("Fetching answer file from partition failed: 
{err}"),
+            }
+            match FetchFromHTTP::get_answer(install_settings) {
+                Ok(answer) => return Ok(answer),
+                Err(err) => info!("Fetching answer file via HTTP failed: 
{err}"),
+            }
+        },
+        AutoInstModes::Included => {
+            let answer_path = PathBuf::from("/cdrom/answer.toml");
+            match fetch_plugins::utils::get_answer_file(&answer_path) {
+                Ok(answer) => return Ok(answer),
+                Err(err) => info!("Fetching answer file from ISO failed: 
{err}"),
+            }
+        },
+        AutoInstModes::Partition => {
+            match FetchFromPartition::get_answer() {
+                Ok(answer) => return Ok(answer),
+                Err(err) => info!("Fetching answer file from partition failed: 
{err}"),
+            }
+        },
+        AutoInstModes::Http => {
+            match FetchFromHTTP::get_answer(install_settings) {
+                Ok(answer) => return Ok(answer),
+                Err(err) => info!("Fetching answer file via HTTP failed: 
{err}"),
+            }
+        },
 
+    }
     Err(Error::msg("Could not find any answer file!"))
 }
 
@@ -34,8 +60,22 @@ fn main() -> ExitCode {
         panic!("could not initialize logging: {err}");
     }
 
-    info!("Fetching answer file");
-    let answer = match fetch_answer() {
+    let raw_install_settings = match fs::read_to_string(AUTOINST_MODE_FILE) {
+        Ok(f) => f,
+        Err(err) => {
+            error!("Could not find needed file '{AUTOINST_MODE_FILE}' in live 
environment: {err}");
+            return ExitCode::FAILURE;
+        },
+    };
+    let install_settings: AutoInstSettings = match 
toml::from_str(raw_install_settings.as_str()) {
+        Ok(content) => content,
+        Err(err) => {
+            error!("Failed to parse '{AUTOINST_MODE_FILE}': {err}");
+            return ExitCode::FAILURE;
+        },
+    };
+
+    let answer = match fetch_answer(&install_settings) {
         Ok(answer) => answer,
         Err(err) => {
             error!("Aborting: {}", err);
-- 
2.39.2



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to