Resuming libvirt guests after Pulseaudio units

I have a well-working PCI-passthrough setup with NixOS using libvirt, where audio from the guest is piped into Pulseaudio. This works, just only not during a reboot where the state of the guest is resumed; if the host is restarted without first shutting down the guest I’m unable to properly start Pulseaudio — the guest must first be shut down before restarting the host.

If this is not done, manual invocation of Pulseaudio yields “bind(): Address already in use”. Running pulseaudio -k yields “No such process”.

As a work-around I tried to apply virtualisation.libvirtd.onShutdown = "shutdown" but this, oddly enough, had no effect.

I figure I could resolve this by making sure guests aren’t resumed until Pulseaudio have been fully started. How would I do this?

Cheers.

The general approach would be to change the libvirt systemd unit to instruct it to start after PulseAudio.

Looking in the nixpkgs source code I see that systemd.services.libvirtd is defined in nixos/modules/virtualisation/libvirtd.nix. So now all that needs to be done is add something like this in the nixos configuration:

{ ... }:
{
  systemd.services.libvirtd.after = [ "pulseaudio.service" ];
}

One complication is the pulseaudio might be tied to a user session. Look in nixos/modules/config/pulseaudio.nix to see if there is anything there.

One complication is the pulseaudio might be tied to a user session.

pulseaudio should run in a user session unless it is running on a dedicated appliance (media center, smart-speaker, or similar) so the proposed fix will not do the trick.

After updating to 18.09 Pulseaudio works as expected on the host, but now the guest has no connection to it; a lot of ALSA/PulseAudio “Unable to connect: Connection refused” errors are logged. Perhaps guest resumes across host reboots using QEMU_AUDIO_DRV=pa QEMU_PA_SERVER=/run/user/1000/pulse/native are not supported?

Looking at nixos/modules/virtualisation/libvirtd.nix the option seems unused; looking into it.

I created a PR so that the option is used, but the guests are still fired up — before the Pulseaudio units, I presume — when powering on the system again,

I have “solved” the problem by setting

systemd.services.libvirt-guests.preStart = ''
  ${pkgs.coreutils}/bin/coreutils --coreutils-prog=sleep 10
''

which works — even when resuming a suspended domain — but I’m not sure of its limitations; I think the domain will eventually start if I idle at the login screen, and there would then be no Pulseaudio daemon to talk to.

Surely, though, there must be a better solution; is it possible to make a system unit depend on a user unit? Or is it possible to somehow force a Pulseaudio to start for a user before that user has logged in?

The alternative is to override ExecStart in libvirt-guests.service to an empty string, requiring one to manually start/resume the domain instead.