Skip to content

Commit a082748

Browse files
services: define a services interface
Signed-off-by: Brian McGillion <bmg.avoin@gmail.com>
1 parent 52e533f commit a082748

File tree

13 files changed

+360
-202
lines changed

13 files changed

+360
-202
lines changed

lib/default.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ in
120120
mkGlobalConfig
121121
# VM composition utilities organized under lib.ghaf.vm.*
122122
vm
123+
# Feature assignment utilities under lib.ghaf.features.*
124+
features
123125
;
124126
};
125127
}

lib/global-config.nix

Lines changed: 268 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,196 @@ rec {
200200
};
201201
};
202202

203-
# Extensible: additional settings discovered during migration
204-
# will be added here as we migrate more VMs
203+
# ═══════════════════════════════════════════════════════════════════════
204+
# FEATURES - Service Assignment Configuration
205+
# ═══════════════════════════════════════════════════════════════════════
206+
#
207+
# Features define which services are enabled and in which VMs they run.
208+
# Each feature has:
209+
# - enable: Whether the feature is available system-wide
210+
# - targetVms: List of VMs that should have this feature
211+
#
212+
# Usage in downstream:
213+
# ghaf.global-config.features.fprint.targetVms = [ "admin-vm" ];
214+
# ghaf.global-config.features.yubikey.targetVms = [ "gui-vm" "admin-vm" ];
215+
#
216+
# VM base modules check: lib.ghaf.features.isEnabledFor globalConfig "fprint" vmName
217+
#
218+
features = {
219+
# Hardware authentication services
220+
fprint = {
221+
enable = mkOption {
222+
type = types.bool;
223+
default = true;
224+
description = "Enable fingerprint authentication support";
225+
};
226+
targetVms = mkOption {
227+
type = types.listOf types.str;
228+
default = [ "gui-vm" ];
229+
example = [
230+
"gui-vm"
231+
"admin-vm"
232+
];
233+
description = "VMs that should have fingerprint support";
234+
};
235+
};
236+
237+
yubikey = {
238+
enable = mkOption {
239+
type = types.bool;
240+
default = true;
241+
description = "Enable Yubikey 2FA support";
242+
};
243+
targetVms = mkOption {
244+
type = types.listOf types.str;
245+
default = [ "gui-vm" ];
246+
example = [
247+
"gui-vm"
248+
"admin-vm"
249+
];
250+
description = "VMs that should have Yubikey support";
251+
};
252+
};
253+
254+
brightness = {
255+
enable = mkOption {
256+
type = types.bool;
257+
default = true;
258+
description = "Enable brightness control via VirtIO";
259+
};
260+
targetVms = mkOption {
261+
type = types.listOf types.str;
262+
default = [ "gui-vm" ];
263+
description = "VMs that should have brightness control";
264+
};
265+
};
266+
267+
# Networking services
268+
wifi = {
269+
enable = mkOption {
270+
type = types.bool;
271+
default = true;
272+
description = "Enable WiFi networking support";
273+
};
274+
targetVms = mkOption {
275+
type = types.listOf types.str;
276+
default = [ "net-vm" ];
277+
description = "VMs that should have WiFi support";
278+
};
279+
};
280+
281+
# Audio services
282+
audio = {
283+
enable = mkOption {
284+
type = types.bool;
285+
default = true;
286+
description = "Enable audio services";
287+
};
288+
targetVms = mkOption {
289+
type = types.listOf types.str;
290+
default = [ "audio-vm" ];
291+
description = "VMs that should have audio support";
292+
};
293+
};
294+
295+
bluetooth = {
296+
enable = mkOption {
297+
type = types.bool;
298+
default = true;
299+
description = "Enable Bluetooth support";
300+
};
301+
targetVms = mkOption {
302+
type = types.listOf types.str;
303+
default = [ "audio-vm" ];
304+
description = "VMs that should have Bluetooth support";
305+
};
306+
};
307+
};
205308
};
206309
};
207310

311+
# ═══════════════════════════════════════════════════════════════════════════
312+
# FEATURE UTILITIES
313+
# ═══════════════════════════════════════════════════════════════════════════
314+
#
315+
# Helper functions for checking and managing service feature assignments.
316+
# These are used by VM base modules to determine which services to enable.
317+
#
318+
# Usage in VM base modules:
319+
# ghaf.services.fprint.enable = lib.ghaf.features.isEnabledFor globalConfig "fprint" vmName;
320+
#
321+
features = {
322+
# Check if a feature should be enabled for a specific VM
323+
#
324+
# Usage:
325+
# lib.ghaf.features.isEnabledFor globalConfig "fprint" "gui-vm"
326+
# # Returns: true if fprint.enable && "gui-vm" in fprint.targetVms
327+
#
328+
# Parameters:
329+
# globalConfig: The ghaf.global-config attribute set (from specialArgs)
330+
# featureName: Name of the feature (e.g., "fprint", "wifi")
331+
# vmName: Name of the VM to check (e.g., "gui-vm", "net-vm")
332+
#
333+
# Returns: bool
334+
isEnabledFor =
335+
globalConfig: featureName: vmName:
336+
let
337+
featuresAttr = globalConfig.features or { };
338+
feature =
339+
featuresAttr.${featureName} or {
340+
enable = false;
341+
targetVms = [ ];
342+
};
343+
in
344+
(feature.enable or false) && builtins.elem vmName (feature.targetVms or [ ]);
345+
346+
# Get all features enabled for a specific VM
347+
#
348+
# Usage:
349+
# lib.ghaf.features.forVm globalConfig "gui-vm"
350+
# # Returns: { fprint = true; yubikey = true; brightness = true; wifi = false; ... }
351+
#
352+
# Parameters:
353+
# globalConfig: The ghaf.global-config attribute set
354+
# vmName: Name of the VM to check
355+
#
356+
# Returns: attrset of featureName -> bool
357+
forVm =
358+
globalConfig: vmName:
359+
let
360+
featuresAttr = globalConfig.features or { };
361+
in
362+
lib.mapAttrs (
363+
_name: feature: (feature.enable or false) && builtins.elem vmName (feature.targetVms or [ ])
364+
) featuresAttr;
365+
366+
# List all available feature names
367+
#
368+
# Usage:
369+
# lib.ghaf.features.available globalConfig
370+
# # Returns: [ "fprint" "yubikey" "brightness" "wifi" "audio" "bluetooth" ]
371+
#
372+
available = globalConfig: builtins.attrNames (globalConfig.features or { });
373+
374+
# Get VMs that have a specific feature enabled
375+
#
376+
# Usage:
377+
# lib.ghaf.features.vmsWithFeature globalConfig "fprint"
378+
# # Returns: [ "gui-vm" ] (or whatever targetVms is set to)
379+
#
380+
vmsWithFeature =
381+
globalConfig: featureName:
382+
let
383+
featuresAttr = globalConfig.features or { };
384+
feature =
385+
featuresAttr.${featureName} or {
386+
enable = false;
387+
targetVms = [ ];
388+
};
389+
in
390+
if feature.enable or false then feature.targetVms or [ ] else [ ];
391+
};
392+
208393
# Predefined global config profiles
209394
# These can be selected and extended in target configurations
210395
profiles = {
@@ -232,6 +417,33 @@ rec {
232417
};
233418
shm.enable = false;
234419
idsvm.mitmproxy.enable = false;
420+
# Feature defaults for debug profile
421+
features = {
422+
fprint = {
423+
enable = true;
424+
targetVms = [ "gui-vm" ];
425+
};
426+
yubikey = {
427+
enable = true;
428+
targetVms = [ "gui-vm" ];
429+
};
430+
brightness = {
431+
enable = true;
432+
targetVms = [ "gui-vm" ];
433+
};
434+
wifi = {
435+
enable = true;
436+
targetVms = [ "net-vm" ];
437+
};
438+
audio = {
439+
enable = true;
440+
targetVms = [ "audio-vm" ];
441+
};
442+
bluetooth = {
443+
enable = true;
444+
targetVms = [ "audio-vm" ];
445+
};
446+
};
235447
};
236448

237449
# Release profile - production settings
@@ -258,6 +470,33 @@ rec {
258470
};
259471
shm.enable = false;
260472
idsvm.mitmproxy.enable = false;
473+
# Feature defaults for release profile
474+
features = {
475+
fprint = {
476+
enable = true;
477+
targetVms = [ "gui-vm" ];
478+
};
479+
yubikey = {
480+
enable = true;
481+
targetVms = [ "gui-vm" ];
482+
};
483+
brightness = {
484+
enable = true;
485+
targetVms = [ "gui-vm" ];
486+
};
487+
wifi = {
488+
enable = true;
489+
targetVms = [ "net-vm" ];
490+
};
491+
audio = {
492+
enable = true;
493+
targetVms = [ "audio-vm" ];
494+
};
495+
bluetooth = {
496+
enable = true;
497+
targetVms = [ "audio-vm" ];
498+
};
499+
};
261500
};
262501

263502
# Minimal profile - bare minimum
@@ -284,6 +523,33 @@ rec {
284523
};
285524
shm.enable = false;
286525
idsvm.mitmproxy.enable = false;
526+
# Feature defaults for minimal profile - all disabled
527+
features = {
528+
fprint = {
529+
enable = false;
530+
targetVms = [ ];
531+
};
532+
yubikey = {
533+
enable = false;
534+
targetVms = [ ];
535+
};
536+
brightness = {
537+
enable = false;
538+
targetVms = [ ];
539+
};
540+
wifi = {
541+
enable = false;
542+
targetVms = [ ];
543+
};
544+
audio = {
545+
enable = false;
546+
targetVms = [ ];
547+
};
548+
bluetooth = {
549+
enable = false;
550+
targetVms = [ ];
551+
};
552+
};
287553
};
288554
};
289555

modules/microvm/audiovm-features/bluetooth.nix

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,25 @@
33
#
44
# Audio VM Bluetooth Feature Module
55
#
6-
# This module enables Bluetooth service in the Audio VM when audio hardware
7-
# passthrough is enabled.
6+
# This module enables Bluetooth service in the Audio VM when bluetooth feature
7+
# is enabled for this VM.
88
#
9-
# Auto-enables when: hostConfig.audiovm.audio == true
9+
# Auto-enables when: globalConfig.features.bluetooth enabled for this VM
1010
#
1111
{
1212
lib,
13-
hostConfig,
13+
globalConfig,
1414
...
1515
}:
1616
let
17-
# Check if audio hardware passthrough is enabled
18-
audioEnabled = hostConfig.audiovm.audio or false;
17+
vmName = "audio-vm";
18+
# Check if bluetooth feature is enabled for this VM
19+
bluetoothEnabled = lib.ghaf.features.isEnabledFor globalConfig "bluetooth" vmName;
1920
in
2021
{
2122
_file = ./bluetooth.nix;
2223

23-
config = lib.mkIf audioEnabled {
24+
config = lib.mkIf bluetoothEnabled {
2425
ghaf.services.bluetooth.enable = true;
2526
};
2627
}

modules/microvm/audiovm-features/default.nix

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Audio VM Features Module
55
#
66
# This module aggregates all Audio VM feature modules and auto-includes them
7-
# based on their respective feature flags in hostConfig.
7+
# based on their respective feature flags in globalConfig.features.
88
#
99
# Usage:
1010
# In profile's lib.nixosSystem call:
@@ -14,17 +14,17 @@
1414
# ];
1515
#
1616
# Feature modules auto-include based on:
17-
# - bluetooth.nix: hostConfig.audiovm.audio (from microvm options)
18-
# - xpadneo.nix: hostConfig.audiovm.audio (from microvm options)
19-
# - hardware-passthrough.nix: hostConfig has hardware devices
17+
# - bluetooth.nix: globalConfig.features.bluetooth (for audio-vm)
18+
# - xpadneo.nix: globalConfig.features.audio (for audio-vm)
19+
# - hardware-passthrough.nix: hardware.definition (from hostConfig)
2020
#
2121
{ ... }:
2222
{
2323
_file = ./default.nix;
2424

2525
imports = [
2626
# All feature modules use mkIf internally to conditionally enable
27-
# based on their respective hostConfig flags
27+
# based on their respective globalConfig.features flags
2828
./bluetooth.nix
2929
./xpadneo.nix
3030
./hardware-passthrough.nix

modules/microvm/audiovm-features/xpadneo.nix

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@
66
# This module configures Xbox controller support (xpadneo) in the Audio VM.
77
# Currently disabled by default but available for future use.
88
#
9-
# Auto-enables when: hostConfig.audiovm.audio == true
9+
# Auto-enables when: globalConfig.features.audio enabled for this VM
1010
#
1111
{
1212
lib,
13-
hostConfig,
13+
globalConfig,
1414
...
1515
}:
1616
let
17-
# Check if audio hardware passthrough is enabled
18-
audioEnabled = hostConfig.audiovm.audio or false;
17+
vmName = "audio-vm";
18+
# Check if audio feature is enabled for this VM
19+
audioEnabled = lib.ghaf.features.isEnabledFor globalConfig "audio" vmName;
1920
in
2021
{
2122
_file = ./xpadneo.nix;

0 commit comments

Comments
 (0)