}
my $hdgb = int($hdsize/(1024*1024));
- die "hardisk '$target_dev' too small (${hdgb}GB)\n" if $hdgb < 8;
+
+ my ($hard_limit, $soft_limit) = (2, 8);
+
+ die "root disk '$target_dev' too small (${hdgb} GB < $hard_limit GB)\n" if $hdgb < $hard_limit;
+ if ($hdgb < $soft_limit) {
+ my $response = display_prompt(
+ "Root disk space ${hdgb} GB is below recommended minimum space of $soft_limit GB,"
+ ." installation might not be successful! Continue?"
+ );
+ die "root disk '$target_dev' too small (${hdgb} GB < $soft_limit GB), and warning not accepted.\n"
+ if $response ne 'ok';
+ }
+
syscmd("sgdisk -Z ${target_dev}");
}
$message .= "or cancel the installation?";
- my $dialog = Gtk3::MessageDialog->new($window, 'modal', 'question', 'ok-cancel', $message);
- my $response = $dialog->run();
- $dialog->destroy();
+ my $response = display_prompt($message);
if ($response eq 'ok') {
for my $vg_uuid (keys %$duplicate_vgs) {
syscmd("/sbin/vgcreate $vgname $lvmdev") == 0 ||
die "unable to create volume group '$vgname'\n";
- my $hdgb = int($os_size/(1024*1024));
- my $space = (($hdgb > 128) ? 16 : ($hdgb/8))*1024*1024;
+ my $hdgb = int($os_size / (1024 * 1024));
+
+ # always leave some space at the end to avoid roudning issues with LVM's physical extent (PE)
+ # size of 4 MB.
+ my $space = $hdgb <= 32 ? 4 * 1024 : (($hdgb > 128 ? 16 : $hdgb / 8) * 1024 * 1024);
my $rootsize;
- my $datasize;
+ my $datasize = 0;
if ($setup->{product} eq 'pve') {
- my $maxroot;
+ my $maxroot_mb;
if ($config_options->{maxroot}) {
- $maxroot = $config_options->{maxroot};
+ $maxroot_mb = $config_options->{maxroot} * 1024;
} else {
- $maxroot = 96;
+ $maxroot_mb = 96 * 1024;
}
- $rootsize = (($hdgb > ($maxroot*4)) ? $maxroot : $hdgb/4)*1024*1024;
-
- my $rest = $os_size - $swap_size - $rootsize; # in KB
+ my $rest = $os_size - $swap_size;
+ my $rest_mb = int($rest / 1024);
- my $minfree;
- if (defined($config_options->{minfree})) {
- $minfree = (($config_options->{minfree}*1024*1024) >= $rest ) ? $space :
- $config_options->{minfree}*1024*1024 ;
+ my $rootsize_mb;
+ if ($rest_mb < 12 * 1024) {
+ # no point in wasting space, try to get us actually installed and align down to 4 MB
+ $rootsize_mb = ($rest_mb - 0.1) & ~3;
+ } elsif ($rest_mb < 48 * 1024) {
+ my $masked = int($rest_mb / 2) & ~3; # align down to 4 MB
+ $rootsize_mb = $masked;
} else {
- $minfree = $space;
+ $rootsize_mb = $rest_mb / 4 + 12 * 1024;
}
- $rest = $rest - $minfree;
+ $rootsize_mb = $maxroot_mb if $rootsize_mb > $maxroot_mb;
+ $rootsize = int($rootsize_mb * 1024);
- if (defined($config_options->{maxvz})) {
- $rest = (($config_options->{maxvz}*1024*1024) <= $rest) ?
- $config_options->{maxvz}*1024*1024 : $rest;
+ $rest -= $rootsize; # in KB
+
+ my $minfree = $space;
+ if (defined(my $cfg_minfree = $config_options->{minfree})) {
+ $minfree = $cfg_minfree * 1024 * 1024 >= $rest ? $space : $cfg_minfree * 1024 * 1024;
+ }
+
+ $rest = int($rest - $minfree) & ~0xFFF; # align down to 4 MB boundaries
+
+ if (defined(my $maxvz = $config_options->{maxvz})) {
+ $rest = $maxvz * 1024 * 1024 <= $rest ? $maxvz * 1024 * 1024 : $rest;
}
$datasize = $rest;
} else {
my $minfree = defined($config_options->{minfree}) ? $config_options->{minfree}*1024*1024 : $space;
- $rootsize = $os_size - $minfree - $swap_size; # in KB
+ $rootsize = int($os_size - $minfree - $swap_size); # in KB
+ $rootsize &= ~0xFFF; # align down to 4 MB boundaries
}
if ($swap_size) {
syscmd("/sbin/lvcreate -Wy --yes -L${rootsize}K -nroot $vgname") == 0 ||
die "unable to create root volume\n";
- if ($datasize > 4*1024*1024) {
+ if ($datasize > 4 * 1024 * 1024) {
my $metadatasize = $datasize/100; # default 1% of data
$metadatasize = 1024*1024 if $metadatasize < 1024*1024; # but at least 1G
$metadatasize = 16*1024*1024 if $metadatasize > 16*1024*1024; # but at most 16G
# otherwise the metadata is taken out of $minfree
- $datasize -= 2*$metadatasize;
+ $datasize -= 2 * $metadatasize;
# 1 4MB PE to allow for rounding
- $datasize -= 4*1024;
+ $datasize -= 4 * 1024;
syscmd("/sbin/lvcreate -Wy --yes -L${datasize}K -ndata $vgname") == 0 ||
die "unable to create data volume\n";
syscmd("/sbin/lvconvert --yes --type thin-pool --poolmetadatasize ${metadatasize}K $vgname/data") == 0 ||
die "unable to create data thin-pool\n";
} else {
+ if ($setup->{product} eq 'pve' && !defined($config_options->{maxvz})) {
+ display_message("Skipping auto-creation of LVM thinpool for guest data due to low space.");
+ }
$datadev = undef;
}
my $hdgb = int($hdsize/(1024*1024));
- my $swapsize;
+ my $swapsize_kb;
if (defined($config_options->{swapsize})) {
- $swapsize = $config_options->{swapsize}*1024*1024;
+ $swapsize_kb = $config_options->{swapsize} * 1024 * 1024;
} else {
- my $ss = int ($total_memory / 1024);
- $ss = 4 if $ss < 4;
- $ss = ($hdgb/8) if $ss > ($hdgb/8);
- $ss = 8 if $ss > 8;
- $swapsize = $ss*1024*1024;
+ my $ss = int($total_memory);
+ $ss = 4096 if $ss < 4096 && $hdgb >= 64;
+ $ss = 2048 if $ss < 2048 && $hdgb >= 32;
+ $ss = 1024 if $ss >= 2048 && $hdgb <= 16;
+ $ss = 512 if $ss < 512;
+ $ss = int($hdgb * 128) if $ss > $hdgb * 128;
+ $ss = 8192 if $ss > 8192;
+ $swapsize_kb = int($ss * 1024) & ~0xFFF; # align to 4 MB to avoid all to odd SWAP size
}
- return $swapsize;
+ return $swapsize_kb;
}
my sub chroot_chown {
# create /etc/aliases.db (/etc/aliases is shipped in the base squashfs)
syscmd("chroot $targetdir /usr/bin/newaliases");
- # enable NTP (timedatectl set-ntp true does not work without DBUS)
- syscmd("chroot $targetdir /bin/systemctl enable systemd-timesyncd.service");
-
unlink "$targetdir/proxmox_install_mode";
# set timezone
syscmd("umount $targetdir/proc");
syscmd("umount $targetdir/sys/firmware/efi/efivars");
syscmd("umount $targetdir/sys");
+ rmdir("$targetdir/mnt/hostrun");
if ($use_zfs) {
syscmd("zfs umount -a") == 0 ||
syscmd("zfs set mountpoint=/ $zfspoolname/ROOT/$zfsrootvolname") == 0 ||
die "zfs set mountpoint failed\n";
- syscmd("zpool set bootfs=$zfspoolname/ROOT/$zfsrootvolname $zfspoolname") == 0 ||
- die "zfs set bootfs failed\n";
+ syscmd("zpool set bootfs=$zfspoolname/ROOT/$zfsrootvolname $zfspoolname") == 0 ||
+ die "zpool set bootfs failed\n";
syscmd("zpool export $zfspoolname");
}
$dialog->destroy();
}
+sub display_prompt {
+ my ($query) = @_;
+
+ my $dialog = Gtk3::MessageDialog->new($window, 'modal', 'question', 'ok-cancel', $query);
+ my $response = $dialog->run();
+ $dialog->destroy();
+
+ return $response;
+}
+
my $ipconf_first_view = 1;
sub create_ipconf_view {
};
# only relevant for raid with its multipl diskX to diskY mappings.
-my $get_hdsize_adjustment = sub {
+my $get_selected_hdsize = sub {
my $hdsize = shift;
return $hdsize if defined($hdsize);
$hdsize //= $disksize;
$hdsize = $disksize if $disksize < $hdsize;
}
- $hdsize //= 0; # fall back to zero, e.g., if none is selected hdsize cannot be any size
- return Gtk3::Adjustment->new($config_options->{hdsize} || $hdsize, 0, $hdsize+1, 1, 1, 1);
+ if (my $cfg_hdsize = $config_options->{hdsize}) {
+ # had the dialog open previously and set an even lower size than the disk selection allows
+ $hdsize = $cfg_hdsize if $cfg_hdsize < $hdsize;
+ }
+ return $hdsize // 0; # fall back to zero, e.g., if none is selected hdsize cannot be any size
};
+my sub update_hdsize_adjustment {
+ my ($adjustment, $hdsize) = @_;
+
+ $hdsize = $get_selected_hdsize->($hdsize);
+ # expect that lower = 0 and step increments = 1 still are valid
+ $adjustment->set_upper($hdsize + 1);
+ $adjustment->set_value($hdsize);
+}
+
+my sub create_hdsize_adjustment {
+ my ($hdsize) = @_;
+ $hdsize = $get_selected_hdsize->($hdsize);
+ # params are: initial value, lower, upper, step increment, page increment, page size
+ return Gtk3::Adjustment->new($config_options->{hdsize} || $hdsize, 0, $hdsize+1, 1, 1, 1);
+}
+
my sub get_hdsize_spin_button {
my $hdsize = shift;
my $hdsize_entry_buffer = Gtk3::EntryBuffer->new(undef, 1);
- my $hdsize_size_adj = $get_hdsize_adjustment->($hdsize);
+ my $hdsize_size_adj = create_hdsize_adjustment($hdsize);
my $spinbutton_hdsize = Gtk3::SpinButton->new($hdsize_size_adj, 1, 1);
$spinbutton_hdsize->set_buffer($hdsize_entry_buffer);
my $diskid = $w->{pve_disk_id};
my $a = $w->get_active - 1;
$config_options->{"disksel${diskid}"} = ($a >= 0) ? $hds->[$a] : undef;
- my $hdsize_adj = $get_hdsize_adjustment->();
for my $btn (@$hdsize_buttons) {
- $btn->set_adjustment($hdsize_adj);
+ update_hdsize_adjustment($btn->get_adjustment());
}
});
my $combo_compress = Gtk3::ComboBoxText->new();
$combo_compress->set_tooltip_text("zfs compression algorithm for rpool dataset");
- my $comp_opts = ["on","off","lzjb","lz4", "lze", "gzip", "zstd"];
+ my $comp_opts = ["on","off","lzjb","lz4", "zle", "gzip", "zstd"];
foreach my $opt (@$comp_opts) {
$combo_compress->append($opt, $opt);
}