Add script for offline generation of the ipxe intermediate artifact

This commit is contained in:
Spyros Seimenis 2021-05-18 14:55:01 +00:00
parent 8fe393ee7d
commit 0c334e3fe1
3 changed files with 212 additions and 0 deletions

157
ipxe/archlinux.ipxe.jinja Executable file
View file

@ -0,0 +1,157 @@
#!ipxe
# Figure out if client is 64-bit capable
cpuid --ext 29 && set cpuarch x86_64 || set cpuarch i686
# allow only trusted images
imgtrust
# initial options
set release {{ releases.0 }}
set extrabootoptions ip=dhcp net.ifnames=0 BOOTIF=01-${netX/mac}
set countrycode
:main
iseq ${cpuarch} x86_64 && goto main_x86_64 || goto main_i686
:main_x86_64
menu Arch Linux Netboot
item --gap Settings
item --gap Architecture: x86_64
item set_release Release: ${release}
isset ${mirrorurl} && item set_mirror Mirror: ${mirrorurl} || item set_mirror Choose a mirror
item set_options Boot options: ${extrabootoptions}
item
isset ${mirrorurl} && item boot Boot Arch Linux || item --gap Boot Arch Linux
item shell Drop to iPXE shell
item reboot Reboot
item exit Exit iPXE
isset ${mirrorurl} && choose --default set_options selected || choose --default set_mirror selected || goto shell
goto ${selected} || goto main
:main_i686
menu Arch Linux Netboot
item --gap ERROR: i686 is no longer supported!
item shell Drop to iPXE shell
item reboot Reboot
item exit Exit iPXE
choose --default shell selected || goto shell
goto ${selected} || goto main
:shell
echo Type 'exit' to get the back to the menu
shell
goto main
:reboot
reboot
:exit
exit
:set_release
menu Arch Linux Netboot: Select Release
item back back
item
item --gap Available releases:
{% for release in releases %}item {{ release }} {{ release }}
{% endfor %}
choose selected || goto main
iseq ${selected} back && goto main ||
set release ${selected}
goto main
:set_mirror
goto select_mirror_country
:select_mirror_country
menu Arch Linux Netboot: Select Mirror
item back back
item
item --gap Custom Configuration:
item custom Enter mirror URL
item
item --gap Select Mirror By Country:
{% for mirrorgroup in mirrors_by_country %}
{% if mirrorgroup.grouper == '' %}
item 00 Global
{% else %}
item {{ mirrorgroup.grouper }} {{ mirrorgroup.grouper_name }}
{% endif %}
{% endfor %}
isset ${countrycode} && choose --default ${countrycode} selected || choose selected || goto main
iseq ${selected} back && goto main ||
iseq ${selected} custom && goto enter_mirror_url ||
set countrycode ${selected}
goto select_mirror_url
:enter_mirror_url
set countrycode
echo Enter the mirror URL including the trailing slash.
echo Example: http://some.host/archlinux/
echo
echo -n Mirror URL: ${} && read mirrorurl || goto select_mirror_country
goto main
:select_mirror_url
goto select_mirror_url_${countrycode} || goto select_mirror_country
{% for mirrorgroup in mirrors_by_country %}
{% if mirrorgroup.grouper == '' %}
:select_mirror_url_00
set countryname Global
{% else %}
:select_mirror_url_{{ mirrorgroup.grouper }}
set countryname {{ mirrorgroup.grouper_name }}
{% endif %}
menu Arch Linux Netboot: Select Mirror
item back back
item
item --gap Available mirrors in ${countryname}
{% for mirror in mirrorgroup.list %}item {{ mirror.url }} {{ mirror.name }}
{% endfor %}
choose selected || goto select_mirror_country
iseq ${selected} back && goto select_mirror_country ||
set mirrorurl ${selected}
goto main
{% endfor %}
:set_options
echo -n Boot options: ${} && read extrabootoptions ||
goto main
:boot
echo Booting Arch Linux x86_64 ${release} from ${mirrorurl}
echo
kernel ${mirrorurl}iso/${release}/arch/boot/x86_64/vmlinuz-linux || goto failed_download
imgverify vmlinuz-linux ${mirrorurl}iso/${release}/arch/boot/x86_64/vmlinuz-linux.ipxe.sig || goto failed_verify
initrd ${mirrorurl}iso/${release}/arch/boot/amd-ucode.img || goto failed_download
imgverify amd-ucode.img ${mirrorurl}iso/${release}/arch/boot/amd-ucode.img.ipxe.sig || goto failed_verify
initrd ${mirrorurl}iso/${release}/arch/boot/intel-ucode.img || goto failed_download
imgverify intel-ucode.img ${mirrorurl}iso/${release}/arch/boot/intel-ucode.img.ipxe.sig || goto failed_verify
initrd ${mirrorurl}iso/${release}/arch/boot/x86_64/initramfs-linux.img || goto failed_download
imgverify initramfs-linux.img ${mirrorurl}iso/${release}/arch/boot/x86_64/initramfs-linux.img.ipxe.sig || goto failed_verify
imgargs vmlinuz-linux initrd=amd-ucode.img initrd=intel-ucode.img initrd=initramfs-linux.img archiso_http_srv=${mirrorurl}iso/${release}/ archisobasedir=arch verify=y ${extrabootoptions}
boot || goto failed_boot
:failed_download
echo
echo Failed to download a file.
goto failed
:failed_verify
echo
echo Failed to verify a file.
goto failed
:failed_boot
echo
echo Boot failed.
goto failed
:failed
echo Press a key to return to the menu.
prompt
imgfree
goto main

49
ipxe/generate_archlinux_ipxe.py Executable file
View file

@ -0,0 +1,49 @@
#!/usr/bin/env python
import os
import urllib.request, json
import jinja2
from collections import namedtuple
from operator import itemgetter
mirrors_url = "https://archlinux.org/mirrors/status/json"
releases_url = "https://archlinux.org/releng/releases/json/"
dir_path = os.path.dirname(os.path.realpath(__file__))
archlinux_ipxe_template = "archlinux.ipxe.jinja"
templateLoader = jinja2.FileSystemLoader(dir_path)
templateEnv = jinja2.Environment(loader=templateLoader)
template = templateEnv.get_template(archlinux_ipxe_template)
releases = []
with urllib.request.urlopen(releases_url) as url:
data = json.loads(url.read())
releases = sorted(data["releases"], key=itemgetter('release_date'), reverse=True)
releases = [ release["version"] for release in releases if release["available"]]
mirrors_by_country = []
with urllib.request.urlopen(mirrors_url) as url:
data = json.loads(url.read())
mirrorurls = []
for mirror in data["urls"]:
if mirror["protocol"] == "http" and mirror["active"] and mirror["isos"]:
keys = ["url", "name", "country_code", "country"]
mirrorObj = namedtuple("Mirror", keys)
mirror = mirrorObj(mirror["url"], mirror["details"].rsplit('/',3)[1], mirror["country_code"], mirror["country"])
mirrorurls.append(mirror)
mirrorurls = sorted(mirrorurls, key=lambda x: x.name)
mirrorurls = sorted(mirrorurls, key=lambda x: x.country)
mirrors_by_country = {}
for mirror in mirrorurls:
if mirror.country_code not in mirrors_by_country.keys():
mirrors_by_country[mirror.country_code] = {"grouper": mirror.country_code, "grouper_name": mirror.country, "list": []}
mirrors_by_country[mirror.country_code]["list"].append({"url": mirror.url, "name": mirror.name})
mirrors_by_country = mirrors_by_country.values()
print((template.render(mirrors_by_country = mirrors_by_country, releases = releases)))

6
ipxe/test.sh Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env bash
python generate_archlinux_ipxe.py
curl https://ipxe.archlinux.org/releng/netboot/archlinux.ipxe > archweb-archlinux.ipxe
diff archweb-archlinux.ipxe archlinux.ipxe