BaseUtilsGentoo/generate_qemu_img.pl

216 lines
5.6 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 );
mountQemuNbd($dest_img);
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);
$utils->execChroot($tempdir_installation, 'useradd', '-m', 'kube');
$utils->execChroot($tempdir_installation, 'gpasswd', '-a', 'kube', 'docker');
$utils->execChroot($tempdir_installation, 'gpasswd', '-a', 'kube', 'wheel');
my $wait_sub = BaseUtils::openWriteCommandChroot($utils, my $fh, $tempdir_installation, 'chpasswd');
say $fh 'kube:kube';
close $fh;
if ($wait_sub->() != 0) {
die 'Unable to chpasswd';
}
};
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>) {
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/nbd1p2', $tempdir_installation;
if ( $return_code != 0 ) {
die 'Unable to mount nbd1p2';
}
my $boot = $tempdir_installation->child('boot');
$boot->mkpath;
$return_code = system 'mount', '/dev/nbd1p1', $boot;
if ( $return_code != 0 ) {
die 'Unable to mount nbd1p1';
}
}
sub retrieveRootUuid {
open my $fh, '-|', 'blkid';
while ( my $line = <$fh> ) {
if ( $line !~ m{/dev/nbd1p2} ) {
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/nbd1p2} ) {
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/nbd1p1} ) {
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');
$fstab->spew_utf8($fstab_contents);
}
sub formatPartitions {
system 'mkfs.vfat', '/dev/nbd1p1';
system 'mkfs.ext4', '/dev/nbd1p2';
}
sub createPartitionTable {
open my $fh, "|-", 'fdisk', '/dev/nbd1';
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', 'nbd';
system 'modprobe', 'nbd';
sleep 5;
}
sub mountQemuNbd ($dest_img) {
my $return_code = system 'qemu-nbd', '--connect=/dev/nbd1', $dest_img;
if ( $return_code != 0 ) {
die 'Unable to mount qemu-nbd.';
}
}
sub umountQemuNbd {
system 'umount', '-R', '/mnt/image';
system 'qemu-nbd', '--disconnect', '/dev/nbd1';
}