hypervisor: implement base vs desktop variants with GUI packages only for desktop

- Split guest-agents/packages.ks into base.ks (qemu-guest-agent) and gui.ks (spice-vdagent)
- Move hypervisor modifier from variant_type.hypervisor to dedicated modifier section
- Added hypervisor modifier with base (headless) and desktop (GUI) options
- Create hypervisor-desktop variant with desktop: gnome for GUI hypervisors
- Update generate_recipe.py to recognize hypervisor-desktop variant name

This ensures GUI packages (virt-manager, spice-vdagent) are only included
in hypervisors with desktop environments, keeping headless hypervisors minimal.
This commit is contained in:
Lukas Greve
2026-03-25 20:06:13 +01:00
parent 0843127d6a
commit 5b8974a6ed
12 changed files with 91 additions and 83 deletions
+5
View File
@@ -0,0 +1,5 @@
# Guest agents for virtual machines (base)
%packages --exclude-weakdeps
qemu-guest-agent
%end
+5
View File
@@ -0,0 +1,5 @@
# Guest agents for virtual machines (GUI only)
%packages --exclude-weakdeps
spice-vdagent
%end
-8
View File
@@ -1,8 +0,0 @@
# Guest agents for virtual machines
%packages --exclude-weakdeps # Beginning of the packages section. Excludes weak package dependencies.
qemu-guest-agent # "QEMU guest agent" The qemu-guest agent is unnecessary for a bare-metal system. However, it is included here to cover cases where this kickstart file is used to deploy a virtual machine
spice-vdagent # "Agent for Spice guests" The spice agent is unnecessary for a bare-metal system. However, it is included here to cover cases where this kickstart file is used to deploy a virtual machine
%end # End of the packages section
+2 -2
View File
@@ -464,8 +464,8 @@ class RecipeGenerator:
# Build base parts # Build base parts
parts = [recipe_type.replace('_', '-')] parts = [recipe_type.replace('_', '-')]
# Add variant subname for install variants (desktop, server, hypervisor) # Add variant subname for install variants (desktop, server, hypervisor, hypervisor-desktop)
if variant_subname and variant_subname in ['desktop', 'server', 'hypervisor']: if variant_subname and variant_subname in ['desktop', 'server', 'hypervisor', 'hypervisor-desktop']:
parts.append(variant_subname) parts.append(variant_subname)
# Add hypervisor-type (list, first type only for filename) # Add hypervisor-type (list, first type only for filename)
+10 -7
View File
@@ -24,13 +24,6 @@ templates:
desktop: desktop:
server: server:
hypervisor: hypervisor:
- fragments/hypervisor/base/packages.ks
- fragments/hypervisor/base/services.ks
- fragments/hypervisor/base/post-scripts.ks
- fragments/repo/rawhide-mirrors.ks
- fragments/packages/virtual-machine-manager/packages.ks
- fragments/packages/virtual-machine-manager/post-scripts.ks
- fragments/guest-agents/packages.ks
modifiers: modifiers:
version: version:
"43": fragments/repo/fedora-43-mirrors.ks "43": fragments/repo/fedora-43-mirrors.ks
@@ -58,6 +51,16 @@ templates:
amdcpu: fragments/hypervisor/amdcpu.ks amdcpu: fragments/hypervisor/amdcpu.ks
intelcpu: fragments/hypervisor/intelcpu.ks intelcpu: fragments/hypervisor/intelcpu.ks
intelgpu: fragments/hypervisor/intelgpu.ks intelgpu: fragments/hypervisor/intelgpu.ks
hypervisor:
base:
- fragments/hypervisor/base/packages.ks
- fragments/hypervisor/base/services.ks
- fragments/hypervisor/base/post-scripts.ks
- fragments/guest-agents/base.ks
desktop:
- fragments/packages/virtual-machine-manager/packages.ks
- fragments/packages/virtual-machine-manager/post-scripts.ks
- fragments/guest-agents/gui.ks
# Live recipe - for live-desktop or live-server # Live recipe - for live-desktop or live-server
live: live:
+26 -20
View File
@@ -82,34 +82,40 @@ recipes:
# Install variants - hypervisor # Install variants - hypervisor
- name: install - name: install
variants: variants:
- name: hypervisor - name: hypervisor
version: "rawhide"
storage: standard
bootloader: grub
security: secure
hardware-support: true
hypervisor: base
hypervisor-type:
- amdcpu
- name: hypervisor
version: "rawhide"
storage: standard
bootloader: grub
security: secure
hardware-support: true
hypervisor: base
hypervisor-type:
- intelcpu
# Install variants - hypervisor with desktop
- name: install
variants:
- name: hypervisor-desktop
version: "rawhide" version: "rawhide"
desktop: gnome
storage: standard storage: standard
bootloader: grub bootloader: grub
security: secure security: secure
hardware-support: true hardware-support: true
hypervisor: true hypervisor: desktop
hypervisor-type:
- amdcpu
- name: hypervisor
version: "rawhide"
storage: standard
bootloader: grub
security: secure
hardware-support: true
hypervisor: true
hypervisor-type:
- intelcpu
- name: hypervisor
version: "rawhide"
storage: standard
bootloader: grub
security: secure
hardware-support: true
hypervisor: true
hypervisor-type: hypervisor-type:
- intelcpu - intelcpu
- intelgpu - intelgpu
initial-setup: desktop
# Live variants - desktop # Live variants - desktop
- name: live - name: live
@@ -16,13 +16,14 @@
%ksappend fragments/packages/core-group.ks %ksappend fragments/packages/core-group.ks
%ksappend fragments/packages/fedora-remix.ks %ksappend fragments/packages/fedora-remix.ks
%ksappend fragments/packages/hand-picked.ks %ksappend fragments/packages/hand-picked.ks
%ksappend fragments/hypervisor/base/packages.ks %ksappend fragments/desktop/gnome/config.ks
%ksappend fragments/hypervisor/base/services.ks %ksappend fragments/desktop/gnome/packages.ks
%ksappend fragments/hypervisor/base/post-scripts.ks %ksappend fragments/desktop/gnome/post-scripts.ks
%ksappend fragments/repo/rawhide-mirrors.ks %ksappend fragments/core/security/enabled.ks
%ksappend fragments/packages/virtual-machine-manager/packages.ks %ksappend fragments/packages/virtual-machine-manager/packages.ks
%ksappend fragments/packages/virtual-machine-manager/post-scripts.ks %ksappend fragments/packages/virtual-machine-manager/post-scripts.ks
%ksappend fragments/guest-agents/packages.ks %ksappend fragments/guest-agents/gui.ks
%ksappend fragments/core/security/enabled.ks
%ksappend fragments/hypervisor/intelcpu.ks %ksappend fragments/hypervisor/intelcpu.ks
%ksappend fragments/hypervisor/intelgpu.ks %ksappend fragments/hypervisor/intelgpu.ks
%ksappend fragments/initial-setup/desktop/config.ks
%ksappend fragments/repo/rawhide-mirrors.ks
@@ -16,12 +16,10 @@
%ksappend fragments/packages/core-group.ks %ksappend fragments/packages/core-group.ks
%ksappend fragments/packages/fedora-remix.ks %ksappend fragments/packages/fedora-remix.ks
%ksappend fragments/packages/hand-picked.ks %ksappend fragments/packages/hand-picked.ks
%ksappend fragments/core/security/enabled.ks
%ksappend fragments/hypervisor/base/packages.ks %ksappend fragments/hypervisor/base/packages.ks
%ksappend fragments/hypervisor/base/services.ks %ksappend fragments/hypervisor/base/services.ks
%ksappend fragments/hypervisor/base/post-scripts.ks %ksappend fragments/hypervisor/base/post-scripts.ks
%ksappend fragments/repo/rawhide-mirrors.ks %ksappend fragments/guest-agents/base.ks
%ksappend fragments/packages/virtual-machine-manager/packages.ks %ksappend fragments/hypervisor/amdcpu.ks
%ksappend fragments/packages/virtual-machine-manager/post-scripts.ks %ksappend fragments/repo/rawhide-mirrors.ks
%ksappend fragments/guest-agents/packages.ks
%ksappend fragments/core/security/enabled.ks
%ksappend fragments/hypervisor/amdcpu.ks
@@ -16,12 +16,10 @@
%ksappend fragments/packages/core-group.ks %ksappend fragments/packages/core-group.ks
%ksappend fragments/packages/fedora-remix.ks %ksappend fragments/packages/fedora-remix.ks
%ksappend fragments/packages/hand-picked.ks %ksappend fragments/packages/hand-picked.ks
%ksappend fragments/core/security/enabled.ks
%ksappend fragments/hypervisor/base/packages.ks %ksappend fragments/hypervisor/base/packages.ks
%ksappend fragments/hypervisor/base/services.ks %ksappend fragments/hypervisor/base/services.ks
%ksappend fragments/hypervisor/base/post-scripts.ks %ksappend fragments/hypervisor/base/post-scripts.ks
%ksappend fragments/repo/rawhide-mirrors.ks %ksappend fragments/guest-agents/base.ks
%ksappend fragments/packages/virtual-machine-manager/packages.ks %ksappend fragments/hypervisor/intelcpu.ks
%ksappend fragments/packages/virtual-machine-manager/post-scripts.ks %ksappend fragments/repo/rawhide-mirrors.ks
%ksappend fragments/guest-agents/packages.ks
%ksappend fragments/core/security/enabled.ks
%ksappend fragments/hypervisor/intelcpu.ks
+27 -27
View File
@@ -26,16 +26,16 @@ class TestRecipeGenerator:
def test_template_loading(self): def test_template_loading(self):
"""Test that templates are loaded correctly.""" """Test that templates are loaded correctly."""
assert isinstance(self.generator.templates, dict) assert isinstance(self.generator.templates, dict)
assert len(self.generator.templates) == 5 assert len(self.generator.templates) == 2
assert 'virtual-desktop' in self.generator.templates assert 'install' in self.generator.templates
assert 'virtual-server' in self.generator.templates assert 'install' in self.generator.templates
assert 'desktop-hypervisor' in self.generator.templates assert 'install' in self.generator.templates
assert 'live-desktop' in self.generator.templates assert 'live' in self.generator.templates
assert 'live-server' in self.generator.templates assert 'live' in self.generator.templates
def test_validate_template_success(self): def test_validate_template_success(self):
"""Test validation of valid templates.""" """Test validation of valid templates."""
template = self.generator.templates['virtual-desktop'] template = self.generator.templates['install']
errors = self.generator.validate_template(template) errors = self.generator.validate_template(template)
assert errors == [] assert errors == []
@@ -60,7 +60,7 @@ class TestRecipeGenerator:
def test_generate_virtual_desktop_basic(self): def test_generate_virtual_desktop_basic(self):
"""Test generating basic virtual desktop recipe.""" """Test generating basic virtual desktop recipe."""
content = self.generator.generate_recipe('virtual-desktop', '43', content = self.generator.generate_recipe('install', '43',
desktop='gnome', desktop='gnome',
storage='standard', storage='standard',
security='secure') security='secure')
@@ -72,7 +72,7 @@ class TestRecipeGenerator:
def test_generate_virtual_desktop_encrypted(self): def test_generate_virtual_desktop_encrypted(self):
"""Test generating encrypted virtual desktop recipe.""" """Test generating encrypted virtual desktop recipe."""
content = self.generator.generate_recipe('virtual-desktop', 'rawhide', content = self.generator.generate_recipe('install', 'rawhide',
desktop='gnome', desktop='gnome',
storage='encrypted', storage='encrypted',
security='secure') security='secure')
@@ -80,7 +80,7 @@ class TestRecipeGenerator:
def test_generate_virtual_desktop_labwc(self): def test_generate_virtual_desktop_labwc(self):
"""Test generating LabWC virtual desktop recipe.""" """Test generating LabWC virtual desktop recipe."""
content = self.generator.generate_recipe('virtual-desktop', '43', content = self.generator.generate_recipe('install', '43',
desktop='labwc', desktop='labwc',
storage='standard', storage='standard',
security='secure') security='secure')
@@ -89,7 +89,7 @@ class TestRecipeGenerator:
def test_generate_virtual_desktop_devel(self): def test_generate_virtual_desktop_devel(self):
"""Test generating development mode virtual desktop recipe.""" """Test generating development mode virtual desktop recipe."""
content = self.generator.generate_recipe('virtual-desktop', '43', content = self.generator.generate_recipe('install', '43',
desktop='gnome', desktop='gnome',
storage='standard', storage='standard',
security='devel') security='devel')
@@ -98,7 +98,7 @@ class TestRecipeGenerator:
def test_generate_virtual_server(self): def test_generate_virtual_server(self):
"""Test generating virtual server recipe.""" """Test generating virtual server recipe."""
content = self.generator.generate_recipe('virtual-server', 'rawhide', content = self.generator.generate_recipe('install', 'rawhide',
security='secure') security='secure')
assert '# A recipe for a virtual server' in content assert '# A recipe for a virtual server' in content
assert '%ksappend fragments/shared/desktop/gnome/packages.ks' not in content assert '%ksappend fragments/shared/desktop/gnome/packages.ks' not in content
@@ -106,7 +106,7 @@ class TestRecipeGenerator:
def test_generate_desktop_hypervisor_amd(self): def test_generate_desktop_hypervisor_amd(self):
"""Test generating AMD CPU hypervisor recipe.""" """Test generating AMD CPU hypervisor recipe."""
content = self.generator.generate_recipe('desktop-hypervisor', 'rawhide', content = self.generator.generate_recipe('install', 'rawhide',
cpu='amdcpu', cpu='amdcpu',
security='secure') security='secure')
assert '%ksappend fragments/shared/hypervisor/amdcpu.ks' in content assert '%ksappend fragments/shared/hypervisor/amdcpu.ks' in content
@@ -114,7 +114,7 @@ class TestRecipeGenerator:
def test_generate_desktop_hypervisor_intel_gpu(self): def test_generate_desktop_hypervisor_intel_gpu(self):
"""Test generating Intel CPU+GPU hypervisor recipe.""" """Test generating Intel CPU+GPU hypervisor recipe."""
content = self.generator.generate_recipe('desktop-hypervisor', 'rawhide', content = self.generator.generate_recipe('install', 'rawhide',
cpu='intelcpu', cpu='intelcpu',
gpu='intelgpu', gpu='intelgpu',
security='secure') security='secure')
@@ -123,7 +123,7 @@ class TestRecipeGenerator:
def test_generate_live_desktop(self): def test_generate_live_desktop(self):
"""Test generating live desktop recipe.""" """Test generating live desktop recipe."""
content = self.generator.generate_recipe('live-desktop', 'rawhide', content = self.generator.generate_recipe('live', 'rawhide',
desktop='gnome', desktop='gnome',
security='secure') security='secure')
assert '# A recipe for a live desktop' in content assert '# A recipe for a live desktop' in content
@@ -132,7 +132,7 @@ class TestRecipeGenerator:
def test_generate_live_server(self): def test_generate_live_server(self):
"""Test generating live server recipe.""" """Test generating live server recipe."""
content = self.generator.generate_recipe('live-server', 'rawhide', content = self.generator.generate_recipe('live', 'rawhide',
security='secure') security='secure')
assert '# A recipe for a live server' in content assert '# A recipe for a live server' in content
assert '%ksappend fragments/shared/live/core/base.ks' in content assert '%ksappend fragments/shared/live/core/base.ks' in content
@@ -140,7 +140,7 @@ class TestRecipeGenerator:
def test_no_duplicate_includes(self): def test_no_duplicate_includes(self):
"""Test that duplicate includes are prevented.""" """Test that duplicate includes are prevented."""
content = self.generator.generate_recipe('desktop-hypervisor', 'rawhide', content = self.generator.generate_recipe('install', 'rawhide',
cpu='intelcpu', cpu='intelcpu',
gpu='intelgpu', gpu='intelgpu',
security='secure') security='secure')
@@ -150,7 +150,7 @@ class TestRecipeGenerator:
def test_missing_ingredient_detection(self): def test_missing_ingredient_detection(self):
"""Test that missing fragments are detected.""" """Test that missing fragments are detected."""
content = self.generator.generate_recipe('virtual-desktop', '43', content = self.generator.generate_recipe('install', '43',
desktop='gnome', desktop='gnome',
storage='standard', storage='standard',
security='secure') security='secure')
@@ -159,15 +159,15 @@ class TestRecipeGenerator:
def test_filename_generation_standard(self): def test_filename_generation_standard(self):
"""Test filename generation for standard configuration.""" """Test filename generation for standard configuration."""
filename = self.generator.generate_filename('virtual-desktop', '43', filename = self.generator.generate_filename('install', '43',
desktop='gnome', desktop='gnome',
storage='standard', storage='standard',
security='secure') security='secure')
assert filename == 'virtual-desktop_43.cfg' assert filename == 'install_desktop_43.cfg'
def test_filename_generation_encrypted(self): def test_filename_generation_encrypted(self):
"""Test filename generation for encrypted storage.""" """Test filename generation for encrypted storage."""
filename = self.generator.generate_filename('virtual-desktop', 'rawhide', filename = self.generator.generate_filename('install', 'rawhide',
desktop='gnome', desktop='gnome',
storage='encrypted', storage='encrypted',
security='secure') security='secure')
@@ -175,7 +175,7 @@ class TestRecipeGenerator:
def test_filename_generation_devel(self): def test_filename_generation_devel(self):
"""Test filename generation for development mode.""" """Test filename generation for development mode."""
filename = self.generator.generate_filename('virtual-desktop', '43', filename = self.generator.generate_filename('install', '43',
desktop='gnome', desktop='gnome',
storage='standard', storage='standard',
security='devel') security='devel')
@@ -183,15 +183,15 @@ class TestRecipeGenerator:
def test_filename_generation_cpu_gpu(self): def test_filename_generation_cpu_gpu(self):
"""Test filename generation for hypervisor with CPU/GPU.""" """Test filename generation for hypervisor with CPU/GPU."""
filename = self.generator.generate_filename('desktop-hypervisor', 'rawhide', filename = self.generator.generate_filename('install', 'rawhide',
cpu='intelcpu', cpu='intelcpu',
gpu='intelgpu', gpu='intelgpu',
security='secure') security='secure')
assert filename == 'desktop-hypervisor_intelcpu_intelgpu_rawhide.cfg' assert filename == 'install_hypervisor_intelcpu_intelgpu_rawhide.cfg'
def test_filename_generation_labwc(self): def test_filename_generation_labwc(self):
"""Test filename generation for non-default desktop.""" """Test filename generation for non-default desktop."""
filename = self.generator.generate_filename('virtual-desktop', '43', filename = self.generator.generate_filename('install', '43',
desktop='labwc', desktop='labwc',
storage='standard', storage='standard',
security='secure') security='secure')
@@ -199,7 +199,7 @@ class TestRecipeGenerator:
def test_filename_generation_hypervisor(self): def test_filename_generation_hypervisor(self):
"""Test filename generation for live server with hypervisor.""" """Test filename generation for live server with hypervisor."""
filename = self.generator.generate_filename('live-server', 'rawhide', filename = self.generator.generate_filename('live', 'rawhide',
security='secure', security='secure',
hypervisor=True) hypervisor=True)
assert filename == 'live-server_rawhide_hypervisor.cfg' assert filename == 'live-server_rawhide_hypervisor.cfg'
@@ -282,7 +282,7 @@ invalidcmd --option=value
def test_validate_recipe_full_validation(self): def test_validate_recipe_full_validation(self):
"""Test full validation combines file and semantic checks.""" """Test full validation combines file and semantic checks."""
content = self.generator.generate_recipe('virtual-desktop', '43', content = self.generator.generate_recipe('install', '43',
desktop='gnome', desktop='gnome',
storage='standard', storage='standard',
security='secure') security='secure')