#[derive(Clone)]
struct InstallerState {
options: InstallerOptions,
- /// FIXME: Remove:
setup_info: SetupInfo,
runtime_info: RuntimeInfo,
locales: LocaleInfo,
_ => cfg!(debug_assertions),
};
- let (locales, runtime_info) = match installer_setup(in_test_mode) {
+ let (setup_info, locales, runtime_info) = match installer_setup(in_test_mode) {
Ok(result) => result,
Err(err) => initial_setup_error(&mut siv, &err),
};
bootdisk: BootdiskOptions::defaults_from(&runtime_info.disks[0]),
timezone: TimezoneOptions::defaults_from(&runtime_info, &locales),
password: Default::default(),
- network: NetworkOptions::from(&runtime_info.network),
+ network: NetworkOptions::defaults_from(&setup_info, &runtime_info.network),
autoreboot: false,
},
- setup_info: setup_info().clone(), // FIXME: REMOVE
+ setup_info,
runtime_info,
locales,
steps: HashMap::new(),
siv.run();
}
-fn installer_setup(in_test_mode: bool) -> Result<(LocaleInfo, RuntimeInfo), String> {
+fn installer_setup(in_test_mode: bool) -> Result<(SetupInfo, LocaleInfo, RuntimeInfo), String> {
let base_path = if in_test_mode { "./testdir" } else { "/" };
let mut path = PathBuf::from(base_path);
path.push("run");
path.push("proxmox-installer");
- let installer_info = {
+ let installer_info: SetupInfo = {
let mut path = path.clone();
path.push("iso-info.json");
setup::read_json(&path).map_err(|err| format!("Failed to retrieve setup info: {err}"))?
};
- init_setup_info(installer_info);
+ init_setup_info(installer_info.clone());
let locale_info = {
let mut path = path.clone();
if runtime_info.disks.is_empty() {
Err("The installer could not find any supported hard disks.".to_owned())
} else {
- Ok((locale_info, runtime_info))
+ Ok((installer_info, locale_info, runtime_info))
}
}
use std::net::{IpAddr, Ipv4Addr};
use std::{cmp, fmt};
-use crate::setup::{LocaleInfo, NetworkInfo, RuntimeInfo};
+use crate::setup::{LocaleInfo, NetworkInfo, RuntimeInfo, SetupInfo};
use crate::utils::{CidrAddress, Fqdn};
use crate::SummaryOption;
impl NetworkOptions {
const DEFAULT_DOMAIN: &str = "example.invalid";
-}
-impl Default for NetworkOptions {
- fn default() -> Self {
- let fqdn = format!(
- "{}.{}",
- crate::current_product().default_hostname(),
- Self::DEFAULT_DOMAIN
- );
- // TODO: Retrieve automatically
- Self {
+ pub fn defaults_from(setup: &SetupInfo, network: &NetworkInfo) -> Self {
+ let mut this = Self {
ifname: String::new(),
- fqdn: fqdn.parse().unwrap(),
+ fqdn: Self::construct_fqdn(network, setup.config.product.default_hostname()),
// Safety: The provided mask will always be valid.
address: CidrAddress::new(Ipv4Addr::UNSPECIFIED, 0).unwrap(),
gateway: Ipv4Addr::UNSPECIFIED.into(),
dns_server: Ipv4Addr::UNSPECIFIED.into(),
- }
- }
-}
-
-impl From<&NetworkInfo> for NetworkOptions {
- fn from(info: &NetworkInfo) -> Self {
- let mut this = Self::default();
+ };
- if let Some(ip) = info.dns.dns.first() {
+ if let Some(ip) = network.dns.dns.first() {
this.dns_server = *ip;
}
- let hostname = info
- .hostname
- .as_deref()
- .unwrap_or_else(|| crate::current_product().default_hostname());
- let domain = info.dns.domain.as_deref().unwrap_or(Self::DEFAULT_DOMAIN);
-
- if let Ok(fqdn) = Fqdn::from(&format!("{hostname}.{domain}")) {
- this.fqdn = fqdn;
- }
-
- if let Some(routes) = &info.routes {
+ if let Some(routes) = &network.routes {
let mut filled = false;
if let Some(gw) = &routes.gateway4 {
- if let Some(iface) = info.interfaces.get(&gw.dev) {
+ if let Some(iface) = network.interfaces.get(&gw.dev) {
this.ifname = iface.name.clone();
if let Some(addresses) = &iface.addresses {
if let Some(addr) = addresses.iter().find(|addr| addr.is_ipv4()) {
}
if !filled {
if let Some(gw) = &routes.gateway6 {
- if let Some(iface) = info.interfaces.get(&gw.dev) {
+ if let Some(iface) = network.interfaces.get(&gw.dev) {
if let Some(addresses) = &iface.addresses {
if let Some(addr) = addresses.iter().find(|addr| addr.is_ipv6()) {
this.ifname = iface.name.clone();
this
}
+
+ fn construct_fqdn(network: &NetworkInfo, default_hostname: &str) -> Fqdn {
+ let hostname = network.hostname.as_deref().unwrap_or(default_hostname);
+
+ let domain = network
+ .dns
+ .domain
+ .as_deref()
+ .unwrap_or(Self::DEFAULT_DOMAIN);
+
+ Fqdn::from(&format!("{hostname}.{domain}")).unwrap_or_else(|_| {
+ // Safety: This will always result in a valid FQDN, as we control & know
+ // the values of default_hostname (one of "pve", "pmg" or "pbs") and
+ // constant-defined DEFAULT_DOMAIN.
+ Fqdn::from(&format!("{}.{}", default_hostname, Self::DEFAULT_DOMAIN)).unwrap()
+ })
+ }
}
#[derive(Clone, Debug)]
};
use std::{collections::HashMap, path::PathBuf};
- fn fill_setup_info() {
- crate::init_setup_info(SetupInfo {
+ fn dummy_setup_info() -> SetupInfo {
+ SetupInfo {
config: ProductConfig {
fullname: "Proxmox VE".to_owned(),
product: ProxmoxProduct::PVE,
locations: IsoLocations {
iso: PathBuf::new(),
},
- });
+ }
}
#[test]
fn network_options_from_setup_network_info() {
- fill_setup_info();
+ let setup = dummy_setup_info();
let mut interfaces = HashMap::new();
interfaces.insert(
};
assert_eq!(
- NetworkOptions::from(&info),
+ NetworkOptions::defaults_from(&setup, &info),
NetworkOptions {
ifname: "eth0".to_owned(),
fqdn: Fqdn::from("foo.bar.com").unwrap(),
info.hostname = None;
assert_eq!(
- NetworkOptions::from(&info),
+ NetworkOptions::defaults_from(&setup, &info),
NetworkOptions {
ifname: "eth0".to_owned(),
fqdn: Fqdn::from("pve.bar.com").unwrap(),
info.dns.domain = None;
assert_eq!(
- NetworkOptions::from(&info),
+ NetworkOptions::defaults_from(&setup, &info),
NetworkOptions {
ifname: "eth0".to_owned(),
fqdn: Fqdn::from("pve.example.invalid").unwrap(),
info.hostname = Some("foo".to_owned());
assert_eq!(
- NetworkOptions::from(&info),
+ NetworkOptions::defaults_from(&setup, &info),
NetworkOptions {
ifname: "eth0".to_owned(),
fqdn: Fqdn::from("foo.example.invalid").unwrap(),