mirror of
https://git.launchpad.net/livecd-rootfs
synced 2026-03-18 05:27:45 +00:00
Read http-proxy from --http-proxy flag or build-livefs.conf and pass it to the VM at launch time via cloud-init user-data (apt.http_proxy / apt.https_proxy). Also set package_update: true so cloud-init runs apt-get update on first boot, removing the need for an explicit call. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
151 lines
4.0 KiB
Python
Executable File
151 lines
4.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import configparser
|
|
import pathlib
|
|
import subprocess
|
|
import time
|
|
|
|
import click
|
|
|
|
|
|
_CONFIG_FILE = pathlib.Path.home() / ".config" / "livecd-rootfs" / "build-livefs.conf"
|
|
|
|
|
|
def _read_config() -> dict[str, str]:
|
|
cp = configparser.ConfigParser()
|
|
cp.read(_CONFIG_FILE)
|
|
return dict(cp["defaults"]) if "defaults" in cp else {}
|
|
|
|
|
|
@click.command(
|
|
context_settings={"ignore_unknown_options": True, "allow_extra_args": True}
|
|
)
|
|
@click.option("--suite", required=True, help="Ubuntu suite/series (e.g. noble)")
|
|
@click.option(
|
|
"--vm-name",
|
|
default=None,
|
|
help="LXD VM name (default: livefs-builder-{suite})",
|
|
)
|
|
@click.option(
|
|
"--http-proxy",
|
|
default=None,
|
|
help="HTTP proxy URL for apt inside the VM (also read from build-livefs.conf)",
|
|
)
|
|
@click.argument("extra_args", nargs=-1, type=click.UNPROCESSED)
|
|
def main(suite, vm_name, http_proxy, extra_args):
|
|
livecd_rootfs_root = pathlib.Path(__file__).resolve().parent.parent
|
|
vm_name = vm_name or f"livefs-builder-{suite}"
|
|
host_conf = (
|
|
pathlib.Path.home() / ".config" / "livecd-rootfs" / "build-livefs.conf"
|
|
)
|
|
|
|
if http_proxy is None:
|
|
http_proxy = _read_config().get("http-proxy")
|
|
|
|
result = subprocess.run(["lxc", "info", vm_name], capture_output=True)
|
|
if result.returncode != 0:
|
|
launch_cmd = [
|
|
"lxc", "launch", f"ubuntu-daily:{suite}", vm_name, "--vm",
|
|
"--config", "limits.cpu=4",
|
|
"--config", "limits.memory=8GiB",
|
|
"--device", "root,size=100GiB",
|
|
]
|
|
user_data = "#cloud-config\npackage_update: true\n"
|
|
if http_proxy is not None:
|
|
user_data += (
|
|
"apt:\n"
|
|
f" http_proxy: {http_proxy}\n"
|
|
f" https_proxy: {http_proxy}\n"
|
|
)
|
|
launch_cmd += ["--config", f"user.user-data={user_data}"]
|
|
subprocess.run(launch_cmd, check=True)
|
|
|
|
device_info = subprocess.run(
|
|
["lxc", "config", "device", "show", vm_name],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
).stdout
|
|
if "livecd-rootfs" not in device_info:
|
|
subprocess.run(
|
|
[
|
|
"lxc",
|
|
"config",
|
|
"device",
|
|
"add",
|
|
vm_name,
|
|
"livecd-rootfs",
|
|
"disk",
|
|
f"source={livecd_rootfs_root}",
|
|
"path=/srv/livecd-rootfs",
|
|
],
|
|
check=True,
|
|
)
|
|
|
|
info = subprocess.run(
|
|
["lxc", "info", vm_name], capture_output=True, text=True, check=True
|
|
).stdout
|
|
if "Status: STOPPED" in info:
|
|
subprocess.run(["lxc", "start", vm_name], check=True)
|
|
|
|
for _ in range(30):
|
|
result = subprocess.run(
|
|
["lxc", "exec", vm_name, "--", "true"], capture_output=True
|
|
)
|
|
if result.returncode == 0:
|
|
break
|
|
time.sleep(2)
|
|
else:
|
|
raise click.ClickException(f"VM {vm_name!r} did not become ready in time")
|
|
|
|
subprocess.run(
|
|
["lxc", "exec", vm_name, "--", "cloud-init", "status", "--wait"], check=True
|
|
)
|
|
|
|
subprocess.run(
|
|
["lxc", "exec", vm_name, "--", "apt-get", "install", "-y", "livecd-rootfs"],
|
|
check=True,
|
|
)
|
|
|
|
if host_conf.exists():
|
|
subprocess.run(
|
|
[
|
|
"lxc",
|
|
"exec",
|
|
vm_name,
|
|
"--",
|
|
"mkdir",
|
|
"-p",
|
|
"/root/.config/livecd-rootfs",
|
|
],
|
|
check=True,
|
|
)
|
|
subprocess.run(
|
|
[
|
|
"lxc",
|
|
"file",
|
|
"push",
|
|
str(host_conf),
|
|
f"{vm_name}/root/.config/livecd-rootfs/build-livefs.conf",
|
|
],
|
|
check=True,
|
|
)
|
|
|
|
subprocess.run(
|
|
[
|
|
"lxc",
|
|
"exec",
|
|
vm_name,
|
|
"--",
|
|
"/srv/livecd-rootfs/live-build/build-livefs",
|
|
"--suite",
|
|
suite,
|
|
*extra_args,
|
|
],
|
|
check=True,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|