Subject: [bug#27887] [PATCH] services: Add libvirt services

From: Christopher Baines <[email-masked]>
Date: Sat, 19 Aug 2017 12:59:49 +0100

On Fri, 18 Aug 2017 17:49:01 -0700
Ryan Moe <[email-masked]> wrote:

> >> This looks pretty much ready to be merged to me. Later, I'll try
> >> running this on my machine, just to check that it starts
> >> successfully.  
> >
> > So, I've reconfigured my machine to run both services, and also
> > configured libvirt to use libvirt for the socket group, so that I
> > could add libvirt as a supplemental group for my user. I think this
> > has all worked fine.
> >
> > I tried using the virt-manager to connect, but I'm getting the
> > following error at the moment:
> >
> >
> > Unable to connect to libvirt.
> >
> > internal error: Cannot find suitable emulator for x86_64
> >
> > Libvirt URI is: qemu:///system
> >
> > Traceback (most recent call last):
> >   File
> > "/gnu/store/h61dc28cck9lmp25d1r11d3hzzhz5qnj-virt-manager-1.4.2/share/virt-manager/virtManager/connection.py",
> > line 1108, in _open_thread self._populate_initial_state() File
> > "/gnu/store/h61dc28cck9lmp25d1r11d3hzzhz5qnj-virt-manager-1.4.2/share/virt-manager/virtManager/connection.py",
> > line 1062, in _populate_initial_state logging.debug("conn
> > version=%s", self._backend.conn_version()) File
> > "/gnu/store/h61dc28cck9lmp25d1r11d3hzzhz5qnj-virt-manager-1.4.2/share/virt-manager/virtinst/connection.py",
> > line 322, in conn_version self._conn_version =
> > self._libvirtconn.getVersion() File
> > "/gnu/store/a9g2s8404v8v5pm7m7w8yzr56ba1k331-python2-libvirt-3.4.0/lib/python2.7/site-packages/libvirt.py",
> > line 3863, in getVersion if ret == -1: raise libvirtError
> > ('virConnectGetVersion() failed', conn=self) libvirtError: internal
> > error: Cannot find suitable emulator for x86_64  
> 
> 
> Hi Christopher,
> 
> Thank you for taking a look at this. I have been trying to track down
> this issue for about a week now (I use virt-manager and libvirt daily
> so I'm kind of bummed this stopped working). When I originally
> submitted the patch it worked, I swear I wouldn't have submitted it
> otherwise :)
> 
> At some point I ran a guix pull and a guix system reconfigure and it
> stopped working. The only difference I see is that when I submitted
> the patch libvirt 3.5.0 was the current version and now it's 3.6.0.
> I'm not sure why that would have broken it though.
> 
> The error you see is what happens if you install libvirt without qemu.
> As far as I can tell though qemu is installed. It's also weird because
> it works if I execute the exact same command that shepherd does. You
> can try it yourself:
> 
> 1. Start shepherd service
> 2. ps aux | grep libvirtd
> 3. herd stop libvirtd
> 4. As root, run the complete command from 2 and test with
> virt-manager.

I think running outside of the shepherd works, as the environment will
be different. I think you can look at the environment for the running
process with:

  sudo cat /proc/$(pgrep -f libvirtd | head -n1)/environ

What I see when running the service through the shepherd is very
minimal, and doesn't have a value for PATH.

As I understand it, often in Guix, having a minimal runtime environment
might not be a problem, as packages retain references to their
dependencies from when they were built. If you look at the libvirt
package though, qemu is an input, but the output doesn't reference it.

> My initial thought was that it had something to do with how I was
> installing two packages into the system profile. qemu and libvirt both
> end up there so I don't see why it doesn't work though.

My guess is that the system profile isn't relevant here, as the bin
directory of the system profile isn't on the PATH.

I've written a basic system test for the libvirt service (a patch is
attached), and with that I tested what happens if set the PATH for the
service to explicitly include the QEMU package bin directory, and the
test passes for me with this change.

Back to getting this working though. Either wrapping libvirtd during
the package build to have a PATH including qemu, or including qemu in
the service will work, and I guess the deciding factor might be how
many things libvirt may need to access? Are there lots of other bits of
software that libvirt needs at runtime, where the package doesn't
currently reference them?
From f7889f53c29db2a31634052476f4e3e18ec8911e Mon Sep 17 00:00:00 2001
From: Christopher Baines <[email-masked]>
Date: Sat, 19 Aug 2017 12:56:07 +0100
Subject: [PATCH] tests: Add 'libvirt-service-type' test.

* gnu/tests/virtualization.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
---
 gnu/local.mk                 |  1 +
 gnu/tests/virtualization.scm | 96 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+)
 create mode 100644 gnu/tests/virtualization.scm

diff --git a/gnu/local.mk b/gnu/local.mk
index d60c93453..9ed2cf634 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -494,6 +494,7 @@ GNU_SYSTEM_MODULES =				\
   %D%/tests/messaging.scm			\
   %D%/tests/networking.scm			\
   %D%/tests/ssh.scm				\
+  %D%/tests/virtualization.scm			\
   %D%/tests/web.scm
 
 # Modules that do not need to be compiled.
diff --git a/gnu/tests/virtualization.scm b/gnu/tests/virtualization.scm
new file mode 100644
index 000000000..f0cd9e56c
--- /dev/null
+++ b/gnu/tests/virtualization.scm
@@ -0,0 +1,96 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2017 Christopher Baines <[email-masked]>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu tests virtualization)
+  #:use-module (gnu tests)
+  #:use-module (gnu system)
+  #:use-module (gnu system file-systems)
+  #:use-module (gnu system vm)
+  #:use-module (gnu services)
+  #:use-module (gnu services dbus)
+  #:use-module (gnu services networking)
+  #:use-module (gnu services virtualization)
+  #:use-module (gnu packages virtualization)
+  #:use-module (guix gexp)
+  #:use-module (guix store)
+  #:export (%test-libvirt))
+
+(define %libvirt-os
+  (simple-operating-system
+   (dhcp-client-service)
+   (dbus-service)
+   (polkit-service)
+   (service libvirt-service-type)))
+
+(define (run-libvirt-test)
+  "Run tests in %LIBVIRT-OS."
+  (define os
+    (marionette-operating-system
+     %libvirt-os
+     #:imported-modules '((gnu services herd)
+                          (guix combinators))))
+
+  (define vm
+    (virtual-machine
+     (operating-system os)
+     (port-forwardings '())))
+
+  (define test
+    (with-imported-modules '((gnu build marionette))
+      #~(begin
+          (use-modules (srfi srfi-11) (srfi srfi-64)
+                       (gnu build marionette))
+
+          (define marionette
+            (make-marionette (list #$vm)))
+
+          (mkdir #$output)
+          (chdir #$output)
+
+          (test-begin "libvirt")
+
+          ;; Wait for memcached to be up and running.
+          (test-assert "service running"
+            (marionette-eval
+             '(begin
+                (use-modules (gnu services herd))
+                (match (start-service 'libvirtd)
+                  (#f #f)
+                  (('service response-parts ...)
+                   (match (assq-ref response-parts 'running)
+                     ((pid) (number? pid))))))
+             marionette))
+
+          (test-eq "fetch version"
+            0
+            (marionette-eval
+             `(begin
+                (system* ,(string-append #$libvirt "/bin/virsh")
+                         "-c" "qemu:///system" "version"))
+             marionette))
+
+          (test-end)
+          (exit (= (test-runner-fail-count (test-runner-current)) 0)))))
+
+  (gexp->derivation "libvirt-test" test))
+
+(define %test-libvirt
+  (system-test
+   (name "libvirt")
+   (description "Connect to the running LIBVIRT service.")
+   (value (run-libvirt-test))))
-- 
2.14.1