210 lines
5.2 KiB
Perl
210 lines
5.2 KiB
Perl
#!/usr/bin/env perl
|
|
|
|
use v5.36.0;
|
|
|
|
use strict;
|
|
use warnings;
|
|
use utf8;
|
|
|
|
use Path::Tiny;
|
|
use lib path(__FILE__)->parent->child('lib') . '';
|
|
|
|
use BaseUtils;
|
|
use Digest::SHA qw/sha512_base64/;
|
|
|
|
my $utils = BaseUtils->new;
|
|
|
|
main();
|
|
|
|
sub main() {
|
|
die 'Must be superuser.' if $< != 0;
|
|
my $source_dir = shift @ARGV or die 'No source dir passed.';
|
|
$source_dir = path $source_dir;
|
|
my $dest_img = shift @ARGV // 'gentoo.qcow2';
|
|
if ( -e $dest_img ) {
|
|
die "Image $dest_img already exists.";
|
|
}
|
|
$dest_img = path $dest_img;
|
|
my $size_img = shift @ARGV // 1000;
|
|
my $tempdir_installation = path '/mnt/image';
|
|
$tempdir_installation->mkpath;
|
|
if ( $tempdir_installation->children ) {
|
|
die "$tempdir_installation is not empty.";
|
|
}
|
|
eval {
|
|
modprobeNbd();
|
|
createQemuImage( $dest_img, $size_img );
|
|
say 4;
|
|
mountQemuNbd($dest_img);
|
|
say 5;
|
|
createPartitionTable();
|
|
formatPartitions();
|
|
my $root_partuuid = retrieveRootPartuuid();
|
|
my $root_uuid = retrieveRootUuid();
|
|
my $boot_partuuid = retrieveBootPartuuid();
|
|
mountTempDir($tempdir_installation);
|
|
copySystem( $source_dir, $tempdir_installation );
|
|
generateFstab( $tempdir_installation, $boot_partuuid, $root_partuuid );
|
|
my $vmlinuz = $utils->getVmlinuz($tempdir_installation);
|
|
generateExtlinuxConf( $tempdir_installation, $root_partuuid, $vmlinuz );
|
|
installRootUser($tempdir_installation);
|
|
};
|
|
if ($@) {
|
|
say STDERR $@;
|
|
}
|
|
umountQemuNbd();
|
|
}
|
|
|
|
sub installRootUser($tempdir_installation) {
|
|
my $passwd = $tempdir_installation->child('etc/passwd');
|
|
my $passwd_contents = '';
|
|
open my $fh, '<', $passwd;
|
|
while (my $line = <$fh>) {
|
|
say $line;
|
|
if ($line =~ /^root:/) {
|
|
my @fields = split ':', $line;
|
|
$fields[1] = 'x';
|
|
$line = join ':', @fields;
|
|
}
|
|
$passwd_contents .= $line;
|
|
}
|
|
$passwd->spew_utf8($passwd_contents);
|
|
my $shadow = $tempdir_installation->child('etc/shadow');
|
|
$shadow->spew_utf8(<<"EOF");
|
|
root::10770:0:::::
|
|
EOF
|
|
system 'chmod', '640', $shadow;
|
|
}
|
|
|
|
sub generateExtlinuxConf ( $tempdir_installation, $root_partuuid, $vmlinuz ) {
|
|
$root_partuuid =~ s/"//g;
|
|
my $extlinux_conf = <<"EOF";
|
|
DEFAULT gentoo
|
|
LABEL gentoo
|
|
LINUX /$vmlinuz
|
|
APPEND root=$root_partuuid net.ifnames=0 biosdevname=0
|
|
EOF
|
|
$tempdir_installation->child('boot/EFI/BOOT/extlinux.conf')
|
|
->spew_utf8($extlinux_conf);
|
|
}
|
|
|
|
sub copySystem ( $source_dir, $tempdir_installation ) {
|
|
my $return_code = system 'rsync', '-avHAX', '--numeric-ids', '--progress',
|
|
"$source_dir/", "$tempdir_installation/";
|
|
if ( $return_code != 0 ) {
|
|
die 'Unable to copy system in disk.';
|
|
}
|
|
}
|
|
|
|
sub umountTempDir ($tempdir_installation) {
|
|
system 'umount', '-R', $tempdir_installation;
|
|
}
|
|
|
|
sub mountTempDir ($tempdir_installation) {
|
|
my $return_code = system 'mount', '/dev/nbd5p2', $tempdir_installation;
|
|
if ( $return_code != 0 ) {
|
|
die 'Unable to mount nbd5p2';
|
|
}
|
|
my $boot = $tempdir_installation->child('boot');
|
|
$boot->mkpath;
|
|
$return_code = system 'mount', '/dev/nbd5p1', $boot;
|
|
if ( $return_code != 0 ) {
|
|
die 'Unable to mount nbd5p1';
|
|
}
|
|
}
|
|
|
|
sub retrieveRootUuid {
|
|
open my $fh, '-|', 'blkid';
|
|
while ( my $line = <$fh> ) {
|
|
if ( $line !~ m{/dev/nbd5p2} ) {
|
|
next;
|
|
}
|
|
my ($return) = $line =~ /(UUID=\S+)/;
|
|
return $return;
|
|
}
|
|
die 'Unable to find root partuuid.';
|
|
}
|
|
|
|
sub retrieveRootPartuuid {
|
|
open my $fh, '-|', 'blkid';
|
|
while ( my $line = <$fh> ) {
|
|
if ( $line !~ m{/dev/nbd5p2} ) {
|
|
next;
|
|
}
|
|
my ($return) = $line =~ /(PARTUUID=\S+)/;
|
|
return $return;
|
|
}
|
|
die 'Unable to find root partuuid.';
|
|
}
|
|
|
|
sub retrieveBootPartuuid {
|
|
open my $fh, '-|', 'blkid';
|
|
while ( my $line = <$fh> ) {
|
|
if ( $line !~ m{/dev/nbd5p1} ) {
|
|
next;
|
|
}
|
|
my ($return) = $line =~ /(PARTUUID=\S+)/;
|
|
return $return;
|
|
}
|
|
die 'Unable to find boot partuuid.';
|
|
}
|
|
|
|
sub generateFstab ( $tempdir_installation, $boot, $root ) {
|
|
my $fstab_contents = <<"EOF";
|
|
$boot\t/boot\tvfat\tnoauto,noatime\t1 2
|
|
$root\t/\text4\tnoatime\t0 1
|
|
EOF
|
|
my $fstab = $tempdir_installation->child('etc/fstab');
|
|
say $fstab;
|
|
$fstab->spew_utf8($fstab_contents);
|
|
}
|
|
|
|
sub formatPartitions {
|
|
system 'mkfs.vfat', '/dev/nbd5p1';
|
|
system 'mkfs.ext4', '/dev/nbd5p2';
|
|
}
|
|
|
|
sub createPartitionTable {
|
|
open my $fh, "|-", 'fdisk', '/dev/nbd5';
|
|
print $fh <<'EOF';
|
|
g
|
|
n
|
|
|
|
|
|
+20M
|
|
t
|
|
1
|
|
n
|
|
|
|
|
|
|
|
w
|
|
EOF
|
|
close $fh;
|
|
}
|
|
|
|
sub createQemuImage ( $dest_img, $size_img ) {
|
|
my $return_code = system 'qemu-img', 'create', '-f', 'qcow2', $dest_img,
|
|
$size_img . 'M';
|
|
if ( $return_code != 0 ) {
|
|
die 'Unable to create qemu-img.';
|
|
}
|
|
}
|
|
|
|
sub modprobeNbd {
|
|
system 'rmmod', '-f', 'nbd';
|
|
system 'modprobe', 'nbd';
|
|
}
|
|
|
|
sub mountQemuNbd ($dest_img) {
|
|
my $return_code = system 'qemu-nbd', '--connect=/dev/nbd5', $dest_img;
|
|
if ( $return_code != 0 ) {
|
|
die 'Unable to mount qemu-nbd.';
|
|
}
|
|
}
|
|
|
|
sub umountQemuNbd {
|
|
system 'umount', '-R', '/mnt/image';
|
|
system 'qemu-nbd', '--disconnect', '/dev/nbd5';
|
|
}
|