mirror of
https://git.proxmox.com/git/pve-installer
synced 2025-04-28 16:59:06 +00:00

.. to enable the setup of the 'proxmox-first-boot' service, as well as optionally setting the ordering. Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
303 lines
7.6 KiB
Perl
303 lines
7.6 KiB
Perl
package Proxmox::Install::Config;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Carp;
|
|
use JSON qw(from_json to_json);
|
|
|
|
use Proxmox::Log;
|
|
|
|
use Proxmox::Install::ISOEnv;
|
|
use Proxmox::Sys::Net;
|
|
|
|
sub parse_kernel_cmdline {
|
|
my ($cfg) = @_;
|
|
|
|
my $cmdline = Proxmox::Install::RunEnv::get('kernel_cmdline');
|
|
|
|
if ($cmdline =~ s/\b(ext4|xfs)\s?//i) {
|
|
$cfg->{filesys} = $1;
|
|
}
|
|
|
|
if ($cmdline =~ s/\bhdsize=(\d+(\.\d+)?)\s?//i) {
|
|
$cfg->{hdsize} = $1;
|
|
}
|
|
|
|
if ($cmdline =~ s/\bswapsize=(\d+(\.\d+)?)\s?//i) {
|
|
$cfg->{swapsize} = $1;
|
|
}
|
|
|
|
if ($cmdline =~ s/\bmaxroot=(\d+(\.\d+)?)\s?//i) {
|
|
$cfg->{maxroot} = $1;
|
|
}
|
|
|
|
if ($cmdline =~ s/\bminfree=(\d+(\.\d+)?)\s?//i) {
|
|
$cfg->{minfree} = $1;
|
|
}
|
|
|
|
my $iso_env = Proxmox::Install::ISOEnv::get();
|
|
if ($iso_env->{product} eq 'pve') {
|
|
if ($cmdline =~ s/\bmaxvz=(\d+(\.\d+)?)\s?//i) {
|
|
$cfg->{maxvz} = $1;
|
|
}
|
|
}
|
|
|
|
my @filtered = grep {
|
|
$_ !~ m/^(BOOT_IMAGE|root|ramdisk_size|splash|vga)=\S+$/ &&
|
|
$_ !~ m/^(ro|rw|quiet)$/ &&
|
|
$_ !~ m/^(prox(debug|tui|auto)|proxmox-\S+)$/
|
|
} split(/\s+/, $cmdline);
|
|
|
|
$cfg->{target_cmdline} = join(' ', @filtered);
|
|
|
|
return $cfg;
|
|
}
|
|
|
|
|
|
my sub init_cfg {
|
|
my $iso_env = Proxmox::Install::ISOEnv::get();
|
|
|
|
my $country = Proxmox::Install::RunEnv::get('country');
|
|
if (defined($country) && !defined($iso_env->{locales}->{country}->{$country})) {
|
|
log_warn("ignoring detected country '$country', invalid or unknown\n");
|
|
$country = undef;
|
|
}
|
|
|
|
my $initial = {
|
|
# installer behavior related
|
|
autoreboot => 1,
|
|
|
|
# disk and filesystem related
|
|
filesys => 'ext4',
|
|
hdsize => undef,
|
|
swapsize => undef,
|
|
maxroot => undef,
|
|
minfree => undef,
|
|
maxvz => undef,
|
|
zfs_opts => {
|
|
ashift => 12,
|
|
compress => 'on',
|
|
checksum => 'on',
|
|
copies => 1,
|
|
arc_max => Proxmox::Install::RunEnv::default_zfs_arc_max(), # in MiB
|
|
},
|
|
btrfs_opts => {
|
|
compress => 'off',
|
|
},
|
|
# TODO: single disk selection config
|
|
target_hd => undef,
|
|
disk_selection => {},
|
|
existing_storage_auto_rename => 0,
|
|
|
|
# locale
|
|
country => $country,
|
|
timezone => 'Europe/Vienna',
|
|
keymap => 'en-us',
|
|
|
|
# root credentials & details
|
|
root_password => undef,
|
|
mailto => 'mail@example.invalid',
|
|
root_ssh_keys => [],
|
|
|
|
# network related
|
|
mngmt_nic => undef,
|
|
# FIXME: fix call sites and remove below, it's just an ugly relict of GTK GUI and time
|
|
# pressure on creating the single source of truth for installation config
|
|
mngmt_nic_id => undef,
|
|
hostname => undef,
|
|
domain => undef,
|
|
cidr => undef,
|
|
gateway => undef,
|
|
dns => undef,
|
|
target_cmdline => undef,
|
|
|
|
# proxmox-first-boot setup
|
|
first_boot => {
|
|
enabled => 0,
|
|
# Must be kept in sync with proxmox_auto_installer::answer::FirstBootHookServiceOrdering
|
|
# and the service files in the proxmox-first-boot package
|
|
ordering_target => 'multi-user', # one of `network-pre`, `network-online` or `multi-user`
|
|
},
|
|
};
|
|
|
|
$initial = parse_kernel_cmdline($initial);
|
|
|
|
return $initial;
|
|
}
|
|
|
|
# merge a $new hash into the current config, with $new taking precedence
|
|
sub merge {
|
|
my ($new) = @_;
|
|
|
|
my $current = get();
|
|
|
|
for my $k (sort keys $new->%*) { # first check all
|
|
croak "unknown key '$k'" if !exists($current->{$k})
|
|
}
|
|
$current->{$_} = $new->{$_} for sort keys $new->%*; # then merge
|
|
|
|
return $current;
|
|
}
|
|
|
|
my $_cfg = undef; # NOTE: global singleton
|
|
sub get {
|
|
my ($k) = @_;
|
|
$_cfg = init_cfg() if !defined($_cfg);
|
|
return defined($k) ? $_cfg->{$k} : $_cfg;
|
|
}
|
|
|
|
sub set_key {
|
|
my ($k, $v) = @_;
|
|
my $cfg = get();
|
|
croak "unknown key '$k'" if !exists($cfg->{$k});
|
|
$cfg->{$k} = $v;
|
|
}
|
|
|
|
sub set_autoreboot { set_key('autoreboot', $_[0]); }
|
|
sub get_autoreboot { return get('autoreboot'); }
|
|
|
|
sub set_filesys { set_key('filesys', $_[0]); }
|
|
sub get_filesys { return get('filesys'); }
|
|
|
|
sub set_hdsize { set_key('hdsize', $_[0]); }
|
|
sub get_hdsize { return get('hdsize'); }
|
|
|
|
sub set_swapsize { set_key('swapsize', $_[0]); }
|
|
sub get_swapsize { return get('swapsize'); }
|
|
|
|
sub set_maxroot { set_key('maxroot', $_[0]); }
|
|
sub get_maxroot { return get('maxroot'); }
|
|
|
|
sub set_minfree { set_key('minfree', $_[0]); }
|
|
sub get_minfree { return get('minfree'); }
|
|
|
|
sub set_maxvz { set_key('maxvz', $_[0]); }
|
|
sub get_maxvz { return get('maxvz'); }
|
|
|
|
sub set_zfs_opt {
|
|
my ($k, $v) = @_;
|
|
my $zfs_opts = get('zfs_opts');
|
|
croak "unknown zfs opts key '$k'" if !exists($zfs_opts->{$k});
|
|
$zfs_opts->{$k} = $v;
|
|
}
|
|
sub get_zfs_opt {
|
|
my ($k) = @_;
|
|
my $zfs_opts = get('zfs_opts');
|
|
return defined($k) ? $zfs_opts->{$k} : $zfs_opts;
|
|
}
|
|
|
|
sub set_btrfs_opt {
|
|
my ($k, $v) = @_;
|
|
my $opts = get('btrfs_opts');
|
|
croak "unknown btrfs opts key '$k'" if !exists($opts->{$k});
|
|
$opts->{$k} = $v;
|
|
}
|
|
sub get_btrfs_opt {
|
|
my ($k) = @_;
|
|
my $opts = get('btrfs_opts');
|
|
return defined($k) ? $opts->{$k} : $opts;
|
|
}
|
|
|
|
sub set_target_hd { set_key('target_hd', $_[0]); }
|
|
sub get_target_hd { return get('target_hd'); }
|
|
|
|
sub set_disk_selection {
|
|
my ($id, $v) = @_;
|
|
my $disk_selection = get('disk_selection');
|
|
$disk_selection->{$id} = $v;
|
|
}
|
|
sub get_disk_selection {
|
|
my ($id) = @_;
|
|
my $disk_selection = get('disk_selection');
|
|
return defined($id) ? $disk_selection->{$id} : $disk_selection;
|
|
}
|
|
|
|
sub set_country { set_key('country', $_[0]); }
|
|
sub get_country { return get('country'); }
|
|
|
|
sub set_timezone { set_key('timezone', $_[0]); }
|
|
sub get_timezone { return get('timezone'); }
|
|
|
|
sub set_keymap { set_key('keymap', $_[0]); }
|
|
sub get_keymap { return get('keymap'); }
|
|
|
|
sub set_root_password {
|
|
my ($key) = @_;
|
|
croak "unknown root password option '$key'"
|
|
if $key ne 'plain' && $key ne 'hashed';
|
|
|
|
set_key('root_password', { $_[0] => $_[1] });
|
|
}
|
|
|
|
sub get_root_password {
|
|
my ($key) = @_;
|
|
croak "unknown root password option '$key'"
|
|
if $key ne 'plain' && $key ne 'hashed';
|
|
|
|
my $password = get('root_password');
|
|
return defined($password->{$key}) ? $password->{$key} : undef;
|
|
}
|
|
|
|
sub set_mailto { set_key('mailto', $_[0]); }
|
|
sub get_mailto { return get('mailto'); }
|
|
|
|
sub set_root_ssh_keys { set_key('root_ssh_keys', $_[0]); }
|
|
sub get_root_ssh_keys { return get('root_ssh_keys'); }
|
|
|
|
sub set_mngmt_nic { set_key('mngmt_nic', $_[0]); }
|
|
sub get_mngmt_nic { return get('mngmt_nic'); }
|
|
|
|
sub set_mngmt_nic_id { set_key('mngmt_nic_id', $_[0]); }
|
|
sub get_mngmt_nic_id { return get('mngmt_nic_id'); }
|
|
|
|
sub set_hostname { set_key('hostname', $_[0]); }
|
|
sub get_hostname { return get('hostname'); }
|
|
|
|
sub set_domain { set_key('domain', $_[0]); }
|
|
sub get_domain { return get('domain'); }
|
|
|
|
sub get_fqdn { # virtual config
|
|
my ($hostname, $domain) = (get('hostname'), get('domain'));
|
|
return defined($hostname) && defined($domain) ? "${hostname}.${domain}" : undef;
|
|
}
|
|
|
|
sub set_cidr { set_key('cidr', $_[0]); }
|
|
sub get_cidr { return get('cidr'); }
|
|
|
|
sub get_ip_addr { #'virtual config
|
|
my $cidr = get('cidr') // return;
|
|
my ($ip, $mask) = split('/', $cidr);
|
|
return $ip;
|
|
}
|
|
sub get_ip_version { # virtual config
|
|
my $ip = get_ip_addr() // return;
|
|
return Proxmox::Sys::Net::parse_ip_address($ip);
|
|
}
|
|
|
|
sub set_gateway { set_key('gateway', $_[0]); }
|
|
sub get_gateway { return get('gateway'); }
|
|
|
|
sub set_dns { set_key('dns', $_[0]); }
|
|
sub get_dns { return get('dns'); }
|
|
|
|
sub set_target_cmdline { set_key('target_cmdline', $_[0]); }
|
|
sub get_target_cmdline { return get('target_cmdline'); }
|
|
|
|
sub set_existing_storage_auto_rename { set_key('existing_storage_auto_rename', $_[0]); }
|
|
sub get_existing_storage_auto_rename { return get('existing_storage_auto_rename'); }
|
|
|
|
sub set_first_boot_opt {
|
|
my ($k, $v) = @_;
|
|
my $opts = get('first_boot');
|
|
croak "unknown first boot override key '$k'" if !exists($opts->{$k});
|
|
$opts->{$k} = $v;
|
|
}
|
|
sub get_first_boot_opt {
|
|
my ($k) = @_;
|
|
my $opts = get('first_boot');
|
|
return defined($k) ? $opts->{$k} : $opts;
|
|
}
|
|
|
|
1;
|