Brand Hydra OS image and add custom Fastfetch summary
This commit is contained in:
@@ -251,6 +251,21 @@ def enable_user_audio(root):
|
|||||||
raise ImageError('Cannot enable user audio sockets: ' + result.stderr.strip())
|
raise ImageError('Cannot enable user audio sockets: ' + result.stderr.strip())
|
||||||
|
|
||||||
|
|
||||||
|
def brand_os_release(root):
|
||||||
|
"""Override derivative identity while retaining packaged Gentoo release fields."""
|
||||||
|
release = root_path(root, 'etc/os-release')
|
||||||
|
if not release.is_file():
|
||||||
|
release = root_path(root, 'usr/lib/os-release')
|
||||||
|
original = release.read_text() if release.is_file() else ''
|
||||||
|
retained = [line for line in original.splitlines()
|
||||||
|
if not re.match(r'^(NAME|PRETTY_NAME|ID|ID_LIKE)=', line)]
|
||||||
|
retained += ['NAME="Hydra OS"', 'PRETTY_NAME="Hydra OS"',
|
||||||
|
'ID=hydra-os', 'ID_LIKE=gentoo']
|
||||||
|
# Gentoo links /etc/os-release to its packaged file; keep that file intact.
|
||||||
|
remove(root, 'etc/os-release')
|
||||||
|
write(root, 'etc/os-release', '\n'.join(retained) + '\n')
|
||||||
|
|
||||||
|
|
||||||
def configure_rootfs(root, source):
|
def configure_rootfs(root, source):
|
||||||
root, source = Path(root), Path(source)
|
root, source = Path(root), Path(source)
|
||||||
# Refuse incomplete integrations before changing the exported copy.
|
# Refuse incomplete integrations before changing the exported copy.
|
||||||
@@ -264,6 +279,7 @@ def configure_rootfs(root, source):
|
|||||||
alias.symlink_to(kernel.name)
|
alias.symlink_to(kernel.name)
|
||||||
sanitize_rootfs(root)
|
sanitize_rootfs(root)
|
||||||
copy_overlay(root, source / 'image/rootfs')
|
copy_overlay(root, source / 'image/rootfs')
|
||||||
|
brand_os_release(root)
|
||||||
write(root, 'etc/hydra/live-mode/dracut.conf', (source / 'image/dracut.conf').read_text())
|
write(root, 'etc/hydra/live-mode/dracut.conf', (source / 'image/dracut.conf').read_text())
|
||||||
root_path(root, 'etc/hydra/live-mode/dracut.conf.d').mkdir()
|
root_path(root, 'etc/hydra/live-mode/dracut.conf.d').mkdir()
|
||||||
package = root_path(root, 'usr/lib/hydra/hydra')
|
package = root_path(root, 'usr/lib/hydra/hydra')
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ insmod serial
|
|||||||
serial --unit=0 --speed=115200
|
serial --unit=0 --speed=115200
|
||||||
terminal_input console serial
|
terminal_input console serial
|
||||||
terminal_output console serial
|
terminal_output console serial
|
||||||
menuentry "HydraOS live (volatile host root)" {
|
menuentry "Hydra OS live (volatile host root)" {
|
||||||
search --no-floppy --label HYDRA_OS --set=root
|
search --no-floppy --label HYDRA_OS --set=root
|
||||||
linux /boot/vmlinuz root=live:CDLABEL=HYDRA_OS rd.live.image rd.live.overlay.overlayfs=1 ro console=tty0 console=ttyS0,115200n8
|
linux /boot/vmlinuz root=live:CDLABEL=HYDRA_OS rd.live.image rd.live.overlay.overlayfs=1 ro console=tty0 console=ttyS0,115200n8
|
||||||
initrd /boot/initramfs-live.img
|
initrd /boot/initramfs-live.img
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ net-firewall/nftables
|
|||||||
media-video/pipewire
|
media-video/pipewire
|
||||||
media-video/wireplumber
|
media-video/wireplumber
|
||||||
app-admin/sudo
|
app-admin/sudo
|
||||||
|
app-misc/fastfetch
|
||||||
sys-kernel/gentoo-kernel-bin
|
sys-kernel/gentoo-kernel-bin
|
||||||
sys-kernel/linux-firmware
|
sys-kernel/linux-firmware
|
||||||
sys-firmware/sof-firmware
|
sys-firmware/sof-firmware
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
GRUB_DISTRIBUTOR="HydraOS"
|
GRUB_DISTRIBUTOR="Hydra OS"
|
||||||
GRUB_TIMEOUT=5
|
GRUB_TIMEOUT=5
|
||||||
GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,115200n8"
|
GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,115200n8"
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||||
|
"logo": {
|
||||||
|
"type": "file",
|
||||||
|
"source": "/usr/share/hydra/fastfetch.txt",
|
||||||
|
"color": { "1": "cyan", "2": "white" },
|
||||||
|
"padding": { "right": 3 }
|
||||||
|
},
|
||||||
|
"display": {
|
||||||
|
"color": { "keys": "cyan", "title": "white" },
|
||||||
|
"separator": ": ",
|
||||||
|
"percent": { "type": 1 }
|
||||||
|
},
|
||||||
|
"modules": [
|
||||||
|
"title",
|
||||||
|
{ "type": "os", "format": "{pretty-name} {arch}" },
|
||||||
|
"kernel",
|
||||||
|
"uptime",
|
||||||
|
"cpu",
|
||||||
|
"memory",
|
||||||
|
{ "type": "disk", "folders": "/" },
|
||||||
|
"localip"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
HydraOS live medium: changes to the host root are not persistent.
|
Hydra OS live medium: changes to the host root are not persistent.
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
HydraOS: fullscreen VMs with an ordinary Gentoo host underneath.
|
Hydra OS: fullscreen VMs with an ordinary Gentoo host underneath.
|
||||||
Live host changes are volatile. Use sudo hydra-install for the guarded installer.
|
Live host changes are volatile. Use sudo hydra-install for the guarded installer.
|
||||||
Use hydra --help, nmcli, or nmtui to configure VMs and network connections.
|
Use hydra for the VM menu; hydra --help lists commands. fastfetch shows this host.
|
||||||
|
Use sudo nmtui to configure network connections.
|
||||||
Ctrl+Alt+F2 opens local recovery; return to the graphical session on Ctrl+Alt+F1.
|
Ctrl+Alt+F2 opens local recovery; return to the graphical session on Ctrl+Alt+F1.
|
||||||
Guest bridge: 10.203.0.0/24. Routed LAN access requires a route on your LAN router.
|
Guest bridge: 10.203.0.0/24. Routed LAN access requires a route on your LAN router.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Restrict QEMU bridge helper to HydraOS VM users
|
Description=Restrict QEMU bridge helper to Hydra OS VM users
|
||||||
Before=greetd.service
|
Before=greetd.service
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=DHCP and DNS for HydraOS guests
|
Description=DHCP and DNS for Hydra OS guests
|
||||||
Requires=hydra-network.service
|
Requires=hydra-network.service
|
||||||
PartOf=hydra-network.service
|
PartOf=hydra-network.service
|
||||||
After=hydra-network.service NetworkManager.service
|
After=hydra-network.service NetworkManager.service
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=HydraOS guest bridge and Internet NAT
|
Description=Hydra OS guest bridge and Internet NAT
|
||||||
Requires=NetworkManager.service
|
Requires=NetworkManager.service
|
||||||
PartOf=NetworkManager.service
|
PartOf=NetworkManager.service
|
||||||
After=NetworkManager.service
|
After=NetworkManager.service
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
$1 /\ /\ /\
|
||||||
|
.-(o > .-(o > .-(o >
|
||||||
|
/ / / / / /
|
||||||
|
\ \______\ \______\ \
|
||||||
|
\ \ /
|
||||||
|
'---. .---'
|
||||||
|
\ /\/\ /
|
||||||
|
___\/ \/___
|
||||||
|
/______________\
|
||||||
|
$2 H Y D R A O S
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import shlex
|
||||||
|
from pathlib import Path
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from hydra import image
|
||||||
|
|
||||||
|
|
||||||
|
class BrandingTests(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.tmp = tempfile.TemporaryDirectory()
|
||||||
|
self.addCleanup(self.tmp.cleanup)
|
||||||
|
self.root = Path(self.tmp.name) / 'rootfs'
|
||||||
|
self.root.mkdir()
|
||||||
|
version = '6.18.54-gentoo-dist-bin'
|
||||||
|
(self.root / 'lib/modules' / version).mkdir(parents=True)
|
||||||
|
(self.root / 'boot').mkdir()
|
||||||
|
(self.root / 'boot' / ('vmlinuz-' + version)).write_text('kernel')
|
||||||
|
|
||||||
|
def release(self):
|
||||||
|
return dict(line.split('=', 1)[0:1] + shlex.split(line.split('=', 1)[1])
|
||||||
|
for line in (self.root / 'etc/os-release').read_text().splitlines()
|
||||||
|
if line and not line.startswith('#'))
|
||||||
|
|
||||||
|
def test_export_brands_derivative_without_rewriting_packaged_gentoo_metadata(self):
|
||||||
|
vendor = self.root / 'usr/lib/os-release'
|
||||||
|
vendor.parent.mkdir(parents=True)
|
||||||
|
original = "NAME='Gentoo'\nID=gentoo\nPRETTY_NAME='Gentoo Linux'\nVERSION_ID=2.18\nHOME_URL='https://www.gentoo.org/'\n"
|
||||||
|
vendor.write_text(original)
|
||||||
|
(self.root / 'etc').mkdir()
|
||||||
|
(self.root / 'etc/os-release').symlink_to('../usr/lib/os-release')
|
||||||
|
|
||||||
|
image.configure_rootfs(self.root, Path(__file__).resolve().parents[1])
|
||||||
|
|
||||||
|
self.assertEqual(self.release(), {
|
||||||
|
'NAME': 'Hydra OS', 'PRETTY_NAME': 'Hydra OS', 'ID': 'hydra-os',
|
||||||
|
'ID_LIKE': 'gentoo', 'VERSION_ID': '2.18',
|
||||||
|
'HOME_URL': 'https://www.gentoo.org/',
|
||||||
|
})
|
||||||
|
self.assertFalse((self.root / 'etc/os-release').is_symlink())
|
||||||
|
self.assertEqual(vendor.read_text(), original)
|
||||||
|
self.assertEqual((self.root / 'etc/hostname').read_text(), 'hydra-os\n')
|
||||||
|
|
||||||
|
def test_export_can_brand_minimal_payload_without_os_release(self):
|
||||||
|
image.configure_rootfs(self.root, Path(__file__).resolve().parents[1])
|
||||||
|
|
||||||
|
self.assertTrue((self.root / 'etc/os-release').is_file())
|
||||||
|
self.assertEqual(self.release(), {
|
||||||
|
'NAME': 'Hydra OS', 'PRETTY_NAME': 'Hydra OS',
|
||||||
|
'ID': 'hydra-os', 'ID_LIKE': 'gentoo',
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
+2
-2
@@ -256,8 +256,8 @@ sys.exit(result.returncode)
|
|||||||
result = subprocess.run([sys.executable, '-I', '-c', script, str(self.root / 'usr/lib/hydra'), str(manifest)],
|
result = subprocess.run([sys.executable, '-I', '-c', script, str(self.root / 'usr/lib/hydra'), str(manifest)],
|
||||||
cwd=self.tmp.name, text=True, capture_output=True, timeout=20)
|
cwd=self.tmp.name, text=True, capture_output=True, timeout=20)
|
||||||
self.assertEqual(result.returncode, 0, result.stderr)
|
self.assertEqual(result.returncode, 0, result.stderr)
|
||||||
self.assertIn('HydraOS local recovery', result.stdout)
|
self.assertIn('Hydra OS', result.stdout)
|
||||||
self.assertIn('add', result.stdout)
|
self.assertIn('run', result.stdout)
|
||||||
|
|
||||||
def test_installed_updates_exclude_unadapted_qemu_and_viewer_binaries(self):
|
def test_installed_updates_exclude_unadapted_qemu_and_viewer_binaries(self):
|
||||||
self.kernel()
|
self.kernel()
|
||||||
|
|||||||
Reference in New Issue
Block a user