307 lines
9.3 KiB
Python
Executable file
307 lines
9.3 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
# This file is part of VM-Experiments.
|
|
# Licensed under the GPL-3.0-or-later. See LICENSE for details.
|
|
|
|
import subprocess
|
|
import sys
|
|
import os
|
|
import json
|
|
import shutil
|
|
|
|
downloads = "downloads/"
|
|
output = "output/"
|
|
chroot = "chroot/"
|
|
resources = "resources/"
|
|
installer_packages = "linux-image-amd64 grub-pc parted tar dosfstools util-linux e2fsprogs arch-install-scripts"
|
|
installer_amd64 = "http://deb.debian.org/debian/"
|
|
installer_amd64_name = "bookworm"
|
|
not_verbose = True
|
|
clean_tarballs = False
|
|
|
|
|
|
def command(command):
|
|
result = subprocess.run(command, capture_output=not_verbose, text=True, shell=True)
|
|
return result
|
|
|
|
|
|
# chroot associated functions
|
|
def prepare_chroot():
|
|
command(f"sudo mount --bind /dev '{chroot}/dev'")
|
|
command(f"sudo mount --bind /proc '{chroot}/proc'")
|
|
command(f"sudo mount --bind /sys '{chroot}/sys'")
|
|
command(f"sudo cp /etc/resolv.conf '{chroot}/etc/'")
|
|
|
|
|
|
def do_chroot_command(command_input):
|
|
command(f"sudo chroot '{chroot}' /bin/bash -c '{command_input}'")
|
|
|
|
|
|
def close_chroot():
|
|
command(f"sudo umount '{chroot}/dev'")
|
|
command(f"sudo umount '{chroot}/proc'")
|
|
command(f"sudo umount '{chroot}/sys'")
|
|
|
|
|
|
# handle rootfs image from internet
|
|
def rootfs_downloader(link, filename):
|
|
os.chdir(downloads)
|
|
command(f"wget -nc {link}")
|
|
command(f"sudo tar -xzf {filename} -C '../{chroot}'")
|
|
os.chdir("..")
|
|
|
|
|
|
def rootfs_creator(filename):
|
|
os.chdir(output)
|
|
command(f"sudo tar -czf {filename} -C '../{chroot}' .")
|
|
os.chdir("..")
|
|
|
|
|
|
# packaging rootfs
|
|
def rootfs_package(identifier, scripts, extra_files):
|
|
infile = f"{identifier}.tar.gz"
|
|
outfile = f"{identifier}.iso"
|
|
|
|
close_chroot()
|
|
command(f"sudo rm -rf '{chroot}'")
|
|
command(f"sudo mkdir '{chroot}'")
|
|
|
|
command(
|
|
f"sudo debootstrap --arch amd64 {installer_amd64_name} {chroot} {installer_amd64}"
|
|
)
|
|
command(f"sudo cp '{infile}' '{chroot}/rootfs.tar.gz'")
|
|
if clean_tarballs:
|
|
command(f"sudo rm '{infile}'")
|
|
|
|
prepare_chroot()
|
|
do_chroot_command("apt update")
|
|
do_chroot_command(
|
|
f"DEBIAN_FRONTEND=noninteractive apt install -y {installer_packages}"
|
|
)
|
|
do_chroot_command("mkdir -p /etc/systemd/system/getty@tty1.service.d/")
|
|
do_chroot_command("touch /etc/systemd/system/getty@tty1.service.d/override.conf")
|
|
do_chroot_command(
|
|
'echo -e "[Service]\nExecStart=\nExecStart=/sbin/agetty --noclear --autologin root %I \\$TERM" | tee /etc/systemd/system/getty@tty1.service.d/override.conf'
|
|
)
|
|
do_chroot_command("systemctl daemon-reload")
|
|
do_chroot_command("systemctl enable getty@tty1.service")
|
|
do_chroot_command("echo 'localmachine' > /etc/hostname")
|
|
close_chroot()
|
|
|
|
command(f"sudo cp '{resources}/grub.cfg' '{chroot}/boot/grub/grub.cfg'")
|
|
for script in scripts:
|
|
result = script.split("/")[-1]
|
|
command(f"sudo cp '{script}' '{chroot}/root/{result}'")
|
|
command(f"echo './{result}' | sudo tee -a '{chroot}/root/.profile'")
|
|
command(f"echo './{result}' | sudo tee -a '{chroot}/root/.bashrc'")
|
|
|
|
command(f"echo 'umount -R /mnt' | sudo tee -a '{chroot}/root/.profile'")
|
|
command(f"echo 'umount -R /mnt' | sudo tee -a '{chroot}/root/.bashrc'")
|
|
command(f"echo 'reboot' | sudo tee -a '{chroot}/root/.profile'")
|
|
command(f"echo 'reboot' | sudo tee -a '{chroot}/root/.bashrc'")
|
|
|
|
if shutil.which("grub-mkrescue"):
|
|
command(f"sudo grub-mkrescue -o '{outfile}' '{chroot}'")
|
|
elif shutil.which("grub2-mkrescue"):
|
|
command(f"sudo grub2-mkrescue -o '{outfile}' '{chroot}'")
|
|
|
|
command(f"sudo chown $(logname):$(logname) {outfile}")
|
|
|
|
|
|
# distro specific
|
|
def download_rootfs_prepare(
|
|
download_link,
|
|
download_name,
|
|
packages,
|
|
repositories,
|
|
replace_repositories,
|
|
keyrings,
|
|
identifier,
|
|
create_ca,
|
|
preinstall_scripts,
|
|
scripts,
|
|
package_manager,
|
|
extra_files,
|
|
):
|
|
rootfs_downloader(download_link, download_name)
|
|
apt_rootfs_prepare(
|
|
repositories,
|
|
replace_repositories,
|
|
packages,
|
|
identifier,
|
|
create_ca,
|
|
preinstall_scripts,
|
|
scripts,
|
|
extra_files,
|
|
)
|
|
|
|
|
|
def debootstrap_rootfs_prepare(
|
|
download_link,
|
|
download_name,
|
|
packages,
|
|
repositories,
|
|
replace_repositories,
|
|
keyrings,
|
|
identifier,
|
|
create_ca,
|
|
preinstall_scripts,
|
|
scripts,
|
|
package_manager,
|
|
extra_files,
|
|
):
|
|
command(f"sudo debootstrap --arch amd64 {download_name} {chroot} {download_link}")
|
|
apt_rootfs_prepare(
|
|
repositories,
|
|
replace_repositories,
|
|
keyrings,
|
|
packages,
|
|
identifier,
|
|
create_ca,
|
|
preinstall_scripts,
|
|
scripts,
|
|
extra_files,
|
|
)
|
|
|
|
|
|
def apt_rootfs_prepare(
|
|
repositories,
|
|
replace_repositories,
|
|
keyrings,
|
|
packages,
|
|
identifier,
|
|
create_ca,
|
|
preinstall_scripts,
|
|
scripts,
|
|
extra_files,
|
|
):
|
|
prepare_chroot()
|
|
|
|
if replace_repositories:
|
|
overwritten = False
|
|
else:
|
|
overwritten = True
|
|
|
|
for repository in repositories:
|
|
if overwritten:
|
|
do_chroot_command(f"echo '{repository}' >>/etc/apt/sources.list")
|
|
else:
|
|
do_chroot_command(f"echo '{repository}' >/etc/apt/sources.list")
|
|
overwritten + True
|
|
|
|
for extra_file in extra_files:
|
|
command(f"sudo cp '{extra_file}' '{chroot}/root'")
|
|
|
|
do_chroot_command("apt update -y")
|
|
do_chroot_command("apt full-upgrade -y")
|
|
do_chroot_command(f"DEBIAN_FRONTEND=noninteractive apt install -y {packages}")
|
|
do_chroot_command("echo 'localmachine' > /etc/hostname")
|
|
|
|
for preinstall_script in preinstall_scripts:
|
|
command(f"sudo cp {preinstall_script} {chroot}/root")
|
|
file_name = preinstall_script.split("/")[-1]
|
|
do_chroot_command(f"cd root && ./{file_name}")
|
|
|
|
if create_ca:
|
|
command(f"sudo cp {chroot}/etc/ssl/certs/ca.crt {output}")
|
|
|
|
close_chroot()
|
|
rootfs_creator(f"{identifier}.tar.gz")
|
|
rootfs_package(f"{output}{identifier}", scripts, extra_files)
|
|
|
|
|
|
# main
|
|
def main():
|
|
global not_verbose
|
|
global clean_tarballs
|
|
|
|
for index, arg in enumerate(sys.argv):
|
|
match arg:
|
|
case "-v":
|
|
not_verbose = False
|
|
case "--verbose":
|
|
not_verbose = False
|
|
case "-ct":
|
|
clean_tarballs = True
|
|
case "--clean-tarballs":
|
|
clean_tarballs = True
|
|
case "-h":
|
|
print("")
|
|
print("Help for Linux Deployment Scripts:")
|
|
print("")
|
|
print("-h / --help - Shows this menu.")
|
|
print(
|
|
"-v / --verbose - Displays the outputs of the different commands."
|
|
)
|
|
print(
|
|
"-ct / --clean-tarballs - Delete the tar.gz leftovers from the iso generation."
|
|
)
|
|
print("")
|
|
exit()
|
|
case "--help":
|
|
clean_tarballs = True
|
|
case _:
|
|
if index == 0:
|
|
continue
|
|
|
|
command(f"mkdir -p '{downloads}' '{output}'")
|
|
command(f"sudo chown -R $(logname):$(logname) {downloads}")
|
|
command(f"sudo chown -R $(logname):$(logname) {output}")
|
|
close_chroot()
|
|
command(f"sudo rm -rf '{chroot}'")
|
|
command(f"sudo mkdir '{chroot}'")
|
|
|
|
filename = arg
|
|
data = json.load(open(filename, "r"))
|
|
|
|
rootfs_type = data["rootfs_type"]
|
|
download_link = data["download_link"]
|
|
download_name = data["download_name"]
|
|
packages = data["packages"]
|
|
repositories = data["repositories"]
|
|
replace_repositories = bool(data["replace_repositories"])
|
|
keyrings = data["keyrings"]
|
|
identifier = data["identifier"]
|
|
scripts = data["scripts"]
|
|
package_manager = data["package_manager"]
|
|
extra_files = data["extra_files"]
|
|
create_ca = bool(data["create_ca"])
|
|
preinstall_scripts = data["preinstall_scripts"]
|
|
|
|
match rootfs_type:
|
|
case "download":
|
|
download_rootfs_prepare(
|
|
download_link,
|
|
download_name,
|
|
packages,
|
|
repositories,
|
|
replace_repositories,
|
|
keyrings,
|
|
identifier,
|
|
create_ca,
|
|
preinstall_scripts,
|
|
scripts,
|
|
package_manager,
|
|
extra_files,
|
|
)
|
|
case "debootstrap":
|
|
debootstrap_rootfs_prepare(
|
|
download_link,
|
|
download_name,
|
|
packages,
|
|
repositories,
|
|
replace_repositories,
|
|
keyrings,
|
|
identifier,
|
|
create_ca,
|
|
preinstall_scripts,
|
|
scripts,
|
|
package_manager,
|
|
extra_files,
|
|
)
|
|
|
|
close_chroot()
|
|
command(f"sudo rm -rf '{chroot}'")
|
|
|
|
|
|
main()
|