Commit Graph

167 Commits

Author SHA1 Message Date
Daniel P. Berrange
1c04f99970 Remove spurious whitespace between function name & open brackets
The libvirt coding standard is to use 'function(...args...)'
instead of 'function (...args...)'. A non-trivial number of
places did not follow this rule and are fixed in this patch.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-11-02 13:36:49 +00:00
Eric Blake
5c731eb8a5 docs: libvirtd no longer uses abstract namespace
Commit 905be03d2 quit using the abstract namespace, but didn't
update the --help text to match.

* daemon/libvirtd.c (daemonUsage): Correct socket listing.
2012-10-31 10:12:53 -06:00
Cole Robinson
eba36a3878 daemon: Fix LIBVIRT_DEBUG=1 default output
This commit changes the behavior of LIBVIRT_DEBUG=1 libvirtd:

$ git show 7022b09111
commit 7022b09111
Author: Daniel P. Berrange <berrange@redhat.com>
Date:   Thu Sep 27 13:13:09 2012 +0100

    Automatically enable systemd journal logging

    Probe to see if the systemd journal is accessible, and if
    so enable logging to the journal by default, rather than
    stderr (current default under systemd).

Previously  'LIBVIRT_DEBUG=1 /usr/sbin/libvirtd' would show all debug
output to stderr, now it send debug output to the journal.

Only use the journal by default if running in daemon mode, or
if stdin is _not_ a tty. This should make libvirtd launched from
systemd use the journal, but preserve the old behavior in most
situations.
2012-10-25 16:46:23 -04:00
Daniel P. Berrange
3cfc3d7d2c Add JSON serialization of virNetServerClientPtr objects for process re-exec()
Add two new APIs virNetServerClientNewPostExecRestart and
virNetServerClientPreExecRestart which allow a virNetServerClientPtr
object to be created from a JSON object and saved to a
JSON object, for the purpose of re-exec'ing a process.

This includes serialization of the connected socket associated
with the client

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-10-16 15:45:55 +01:00
Daniel P. Berrange
7022b09111 Automatically enable systemd journal logging
Probe to see if the systemd journal is accessible, and if
so enable logging to the journal by default, rather than
stderr (current default under systemd).

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-09-28 16:02:58 +01:00
Daniel P. Berrange
90af1babd4 Don't initialize logging twice in libvirtd
The virInitialize function initializes logging from the env,
so there is no need for another call to virLogSetFromEnv

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-09-28 10:55:25 +01:00
Daniel P. Berrange
9467ab6074 Move virProcess{Kill,Abort,TranslateStatus} into virprocess.{c,h}
Continue consolidation of process functions by moving some
helpers out of command.{c,h} into virprocess.{c,h}

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-09-26 10:09:57 +01:00
Daniel P. Berrange
0fb58ef5cd Rename virPid{Abort,Wait} to virProcess{Abort,Wait}
Change "Pid" to "Process" to align with the virProcessKill
API naming prefix

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-09-26 10:09:57 +01:00
Eric Blake
4ecb723b9e maint: fix up copyright notice inconsistencies
https://www.gnu.org/licenses/gpl-howto.html recommends that
the 'If not, see <url>.' phrase be a separate sentence.

* tests/securityselinuxhelper.c: Remove doubled line.
* tests/securityselinuxtest.c: Likewise.
* globally: s/;  If/.  If/
2012-09-20 16:30:55 -06:00
Doug Goldstein
b95ad92e05 build: define WITH_INTERFACE for the driver
Based exclusively on work by Eric Blake in a patch posted with the same
subject. However some modifications related to comments and my plans to
add another backend.

Added WITH_INTERFACE as the only automake variable deciding whether to
build the driver and using WITH_NETCF to identify that we're wanting to
use the netcf library as the backend.

* configure.ac: Added with_interface
* src/interface/netcf_driver.c: Renamed..
* src/interface/interface_backend_netcf.c: ..to this to match storage.
* src/interface/netcf_driver.h: Renamed..
* src/interface/interface_driver.h: ..to this.
* daemon/Makefile.am: Respect WITH_INTERFACE and WITH_NETCF.
* libvirt.spec.in: Add RPM support for --with-interface
2012-09-19 08:27:01 -06:00
Jim Fehlig
f781e27653 Fix xen driver following changes to make it stateful
Recent work to improve support for loadable driver modules introduced
a regression in the xen driver.  The legacy xen driver is now a
stateful, libvirtd driver but was not being registered when building
without driver modules.

A slight behavior change was also noted in the xen drivers when
built as driver modules.  Previously, explicitly specifying a
connection URI was not necessary, but now

Compiled against library: libvirt 0.10.0
Using library: libvirt 0.10.0
Using API: QEMU 0.10.0
error: failed to get the hypervisor version
error: internal error Cannot find suitable emulator for x86_64

The xen drivers need to be registered before the qemu driver since
the qemu driver will return success with a null connection URI.
This ordering is safe since the xen drivers will decline when not
running the xen kernel.
2012-08-31 10:28:55 +08:00
Daniel Veillard
d3bbe33880 Portability fixes for non-linux or old linux platforms
The commits d575679401 and
080bf330e3 made use directly of
macro defined in recent linux netlink version. Make those
part conditional on the definition

* daemon/libvirtd.c: do not use NETLINK_ROUTE and NETLINK_KOBJECT_UEVENT
  without some check first
2012-08-29 09:21:38 +08:00
Tang Chen
080bf330e3 Add uevent netlink service.
This patch adds a new netlink service with NETLINK_KOBJECT_UEVENT
protocol hotplug event.

Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
2012-08-22 18:26:15 +08:00
Tang Chen
15a71e6059 Introduce virNetlinkEventServiceStopAll() to stop all netlink services.
This patch introduce virNetlinkEventServiceStopAll() to stop
all the monitors to receive netlink messages for libvirtd.

Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
2012-08-22 18:23:58 +08:00
Tang Chen
d575679401 Improve netlink to support all protocol.
This patch improve all the API in virnetlink.c to support
all kinds of netlink protocols, and make all netlink sockets
be able to join in groups.

Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
2012-08-22 18:23:58 +08:00
Jiri Denemark
15f5e16f4e daemon: Autodetect lock driver directory
When running libvirtd from a build directory, libvirtd would load lock
drivers from system directory unless explicitly overridden by setting
LIBVIRT_LOCK_MANAGER_PLUGIN_DIR environment variable. Since we already
autodetect driver directory if libvirt is build with driver modules, we
can use the same trick to automagically set lock driver directory.
2012-08-21 18:05:19 +02:00
Doug Goldstein
c7447ab147 Update libvirtd --help output to match code
Updated the paths that libvirtd --help says are used when run as
non-root to match what the code actually does.
2012-08-15 21:40:39 +08:00
Daniel P. Berrange
39b5e4d4d8 Refactor RPC client private data setup
Currently there is a hook function that is invoked when a
new client connection comes in, which allows an app to
setup private data. This setup will make it difficult to
serialize client state during process re-exec(). Change to
a model where the app registers a callback when creating
the virNetServerPtr instance, which is used to allocate
the client private data immediately during virNetClientPtr
construction.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-08-15 10:59:10 +01:00
Daniel P. Berrange
958499b0c1 Turn virNetServer* into virObject instances
Make all the virNetServer* objects use the virObject APIs
for reference counting

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-08-07 11:47:55 +01:00
Daniel P. Berrange
e10e1969d5 Turn virNetTLSContext and virNetTLSSession into virObject instances
Make virNetTLSContext and virNetTLSSession use the virObject
APIs for reference counting

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-08-07 11:47:41 +01:00
Jiri Denemark
b5c5ad365e daemon: Portable auto-detection of driver module directory
When running libvirtd from a build directory on a system with unmodified
libtool, libvirtd's binary is not renamed as "lt-libvirtd". Check for
"/daemon/.libs/libvirtd" in addition to "lt-libvirtd".
2012-08-02 16:17:12 +02:00
Daniel P. Berrange
b49890de82 Remove manual one-shot global initializers
Remove the use of a manually run virLogStartup and
virNodeSuspendInitialize methods. Instead make sure they
are automatically run using VIR_ONCE_GLOBAL_INIT

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-08-02 11:50:46 +01:00
Osier Yang
98518178a2 daemon: Fix the wrong macro name
WITH_INTERFACE is not defined, it should be WITH_NETCF there to load
the interface driver.

Eric posted patch weeks ago to resolve the problems in the whole
build system, but it's not finalised yet:

https://www.redhat.com/archives/libvir-list/2012-June/msg01299.html

I'm going to simply fix the wrong macro name here so that the
interface driver could loaded, and continue the work on the listing
API for interface driver.
2012-07-24 15:45:20 -06:00
Daniel P. Berrange
e537a31637 More advanced auto-detection of driver module directory
When running directly from GIT, libvirtd attempts to locate
the directory containing loadable modules. This currently
only works if executing libvirtd with a CWD inside the libvirt
source tree. Switch to locate based on the path to the current
binary instead
2012-07-24 09:21:19 +01:00
Osier Yang
f9ce7dad60 Desert the FSF address in copyright
Per the FSF address could be changed from time to time, and GNU
recommends the following now: (http://www.gnu.org/licenses/gpl-howto.html)

  You should have received a copy of the GNU General Public License
  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.

This patch removes the explicit FSF address, and uses above instead
(of course, with inserting 'Lesser' before 'General').

Except a bunch of files for security driver, all others are changed
automatically, the copyright for securify files are not complete,
that's why to do it manually:

  src/security/security_selinux.h
  src/security/security_driver.h
  src/security/security_selinux.c
  src/security/security_apparmor.h
  src/security/security_apparmor.c
  src/security/security_driver.c
2012-07-23 10:50:50 +08:00
Daniel P. Berrange
c6b2d5d082 Add a opaque parameter to the RPC client init callback
The callback that is invoked when a new RPC client is
initialized does not have any opaque parameter. Add
one so that custom data can be passed into the callback

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-05 10:46:09 +01:00
Daniel P. Berrange
50312d4b91 Add more debug logging for libvirtd startup
To facilitate future troubleshooting add a bunch more debugging
statements into important startup parts of libvirt
2012-06-15 15:33:51 +01:00
Daniel P. Berrange
0ec8262092 Fix privileges on /var/run/libvirt directory
Previous commit

  commit 32a9aac2e0
  Author: William Jon McCann <william.jon.mccann@gmail.com>
  Date:   Thu May 3 12:36:27 2012 -0400

    Use XDG Base Directories instead of storing in home directory

Accidentally changed the umask when creating /var/run/libvirt
to 077. This prevents /var/run/libvirt being readable by non-root,
which is required for non-root to connect to libvirtd. Fix the
code so that umask 077 is only used for the non-privileged libvirtd
instance.
2012-06-11 15:57:12 +01:00
Daniel P. Berrange
19c08b5644 Only migrate profile in non-privileged libvirtd instance
Only the non-privileged libvirtd instance uses $HOME. So avoid
running the code for migrating to XDG directories unless using
a non-privileged libvirtd
2012-06-11 15:57:12 +01:00
Eric Blake
3c3644d30f build: ensure storage driver is used
Commit 1c275e9a accidentally dropped the storage driver from
libvirtd, because it depended on a C preprocessor macro that
was not defined.  Furthermore, if you do './configure
--without-storage-dir --with-storage-disk' or any other combination
where you explicitly build a subset of storage backends excluding
the dir backend, then the build is broken.

Based on analysis by Osier Yang.

* configure.ac (WITH_STORAGE): Define top-level conditional.
* src/Makefile.am (mod_LTLIBRARIES): Build driver even when
storage_dir is disabled.
* daemon/libvirtd.c: Pick up storage driver for any backend, not
just dir.
* daemon/Makefile.am (libvirtd_LDADD): Likewise.
2012-06-06 12:16:07 +08:00
Daniel P. Berrange
517368a377 Remove uid param from directory lookup APIs
Remove the uid param from virGetUserConfigDirectory,
virGetUserCacheDirectory, virGetUserRuntimeDirectory,
and virGetUserDirectory

These functions were universally called with the
results of getuid() or geteuid(). To make it practical
to port to Win32, remove the uid parameter and hardcode
geteuid()

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-05-28 10:55:06 +01:00
Daniel P. Berrange
b47637261c Override default driver dir when running from GIT
* daemon/libvirtd.c: Set custom driver module dir if the current
  binary name is 'lt-libvirtd' (indicating execution directly
  from GIT checkout)
* src/driver.c, src/driver.h, src/libvirt_driver_modules.syms: Add
  virDriverModuleInitialize to allow driver module location to
  be changed

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-05-24 13:18:01 +01:00
Daniel P. Berrange
1c275e9afa Only build server side drivers as modules
The driver modules all use symbols which are defined in libvirt.so.
Thus for loading of modules to work, the binary that libvirt.so
is linked to must export its symbols back to modules. If the
libvirt.so itself is dlopen()d then the RTLD_GLOBAL flag must
be set. Unfortunately few, if any, programming languages use
the RTLD_GLOBAL flag when loading modules :-( This means is it
not practical to use driver modules for any libvirt client side
drivers (OpenVZ, VMWare, Hyper-V, Remote client, test).

This patch changes the build process so only server side drivers
are built as modules (Xen, QEMU, LXC, UML)

* daemon/libvirtd.c: Add missing load of 'interface' driver
* src/Makefile.am: Only build server side drivers as modules
* src/libvirt.c: Don't load any driver modules

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-05-24 13:18:00 +01:00
Daniel P. Berrange
51bcb09fe9 Reject any non-option command line arguments
Due to a bug in editing /etc/sysconfig/libvirtd, VDSM was causing
libvirt processes to run with the following command line args

   /usr/sbin/libvirtd --listen '#' 'by vdsm'

While it correctly rejects any invalid option flags, libvirtd
was not rejecting any non-option command line arguments

* daemon/libvirtd.c: Reject non-option argv
2012-05-16 12:03:02 +01:00
Daniel P. Berrange
905be03d20 Move user libvirtd socket out of abstract namespace
The current unprivileged user libvirtd sockets are in the abstract
namespace. This has a number of problems

 - You can't connect to them remotely using the nc/ssh tunnel
 - This is not portable for OS-X, BSD & probably others
 - Parent directory permissions don't apply
2012-05-15 16:29:55 +01:00
William Jon McCann
32a9aac2e0 Use XDG Base Directories instead of storing in home directory
As defined in:
http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html

This offers a number of advantages:
 * Allows sharing a home directory between different machines, or
sessions (eg. using NFS)
 * Cleanly separates cache, runtime (eg. sockets), or app data from
user settings
 * Supports performing smart or selective migration of settings
between different OS versions
 * Supports reseting settings without breaking things
 * Makes it possible to clear cache data to make room when the disk
is filling up
 * Allows us to write a robust and efficient backup solution
 * Allows an admin flexibility to change where data and settings are stored
 * Dramatically reduces the complexity and incoherence of the
system for administrators
2012-05-14 15:15:58 +01:00
Laine Stump
642973135c util: fix libvirtd startup failure due to netlink error
This is part of the solution to the problem detailed in:

  https://bugzilla.redhat.com/show_bug.cgi?id=816465

and further detailed in

  https://www.redhat.com/archives/libvir-list/2012-May/msg00202.htm

A short explanation is included in the comments of the patch itself.

Note that this patch by itself breaks communication between lldpad and
libvirtd, so the other 3 patches in the series must be applied at the
same time as this patch.
2012-05-07 14:25:43 -04:00
Daniel P. Berrange
2223ea984c The policy kit and HAL node device drivers both require a
DBus connection. The HAL device code further requires that
the DBus connection is integrated with the event loop and
provides such glue logic itself.

The forthcoming FirewallD integration also requires a
dbus connection with event loop integration. Thus we need
to pull the current event loop glue out of the HAL driver.

Thus we create src/util/virdbus.{c,h} files. This contains
just one method virDBusGetSystemBus() which obtains a handle
to the single shared system bus instance, with event glue
automagically setup.
2012-04-19 17:03:10 +01:00
Daniel P. Berrange
a4475839dd Switch libvirtd config loading code to use error APIs
Using VIR_ERROR means the test suite can't catch error messages
easily. Use the proper error reporting APIs instead
2012-04-10 11:12:27 +01:00
Daniel P. Berrange
6e6e9bebc2 Add API for loading daemon config from in-memory blob
Rename existing daemonConfigLoad API to daemonConfigLoadFile and
add an alternative daemonConfigLoadData

* daemon/libvirtd-config.c, daemon/libvirtd-config.h: Add
  daemonConfigLoadData and rename daemonConfigLoad to
  daemonConfigLoadFile
* daemon/libvirtd.c: Update for renamed API
2012-04-10 11:11:12 +01:00
Daniel P. Berrange
db46f3cefe Split libvirtd config file loading out into separate files
To enable creation of unit tests, split the libvirtd config file
loading code out into separate files.

* daemon/libvirtd.c: Delete config loading code / structs
* daemon/libvirtd-config.c, daemon/libvirtd-config.h: Config
  file loading APIs

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-04-10 11:08:51 +01:00
Daniel P. Berrange
ec8cae93db Consistent style for usage of sizeof operator
The code is splattered with a mix of

  sizeof foo
  sizeof (foo)
  sizeof(foo)

Standardize on sizeof(foo) and add a syntax check rule to
enforce it

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-03-30 11:47:24 +01:00
Stef Walter
53e1d56dd4 Change the default of mdns_adv to false
* Don't advertise information on the network without consent of
   the user, either through manual configuration, or a user
   interface that drives this option.
 * Since libvirtd must be configured for network access anyway
   (for all but ssh), this setting was not useful "out of the box",
   so changing this default setting does not remove "out of the box"
   functionality.
2012-03-27 09:54:49 -06:00
Eric Blake
3e2c3d8f6d build: use correct type for pid and similar types
No thanks to 64-bit windows, with 64-bit pid_t, we have to avoid
constructs like 'int pid'.  Our API in libvirt-qemu cannot be
changed without breaking ABI; but then again, libvirt-qemu can
only be used on systems that support UNIX sockets, which rules
out Windows (even if qemu could be compiled there) - so for all
points on the call chain that interact with this API decision,
we require a different variable name to make it clear that we
audited the use for safety.

Adding a syntax-check rule only solves half the battle; anywhere
that uses printf on a pid_t still needs to be converted, but that
will be a separate patch.

* cfg.mk (sc_correct_id_types): New syntax check.
* src/libvirt-qemu.c (virDomainQemuAttach): Document why we didn't
use pid_t for pid, and validate for overflow.
* include/libvirt/libvirt-qemu.h (virDomainQemuAttach): Tweak name
for syntax check.
* src/vmware/vmware_conf.c (vmwareExtractPid): Likewise.
* src/driver.h (virDrvDomainQemuAttach): Likewise.
* tools/virsh.c (cmdQemuAttach): Likewise.
* src/remote/qemu_protocol.x (qemu_domain_attach_args): Likewise.
* src/qemu_protocol-structs (qemu_domain_attach_args): Likewise.
* src/util/cgroup.c (virCgroupPidCode, virCgroupKillInternal):
Likewise.
* src/qemu/qemu_command.c(qemuParseProcFileStrings): Likewise.
(qemuParseCommandLinePid): Use pid_t for pid.
* daemon/libvirtd.c (daemonForkIntoBackground): Likewise.
* src/conf/domain_conf.h (_virDomainObj): Likewise.
* src/probes.d (rpc_socket_new): Likewise.
* src/qemu/qemu_command.h (qemuParseCommandLinePid): Likewise.
* src/qemu/qemu_driver.c (qemudGetProcessInfo, qemuDomainAttach):
Likewise.
* src/qemu/qemu_process.c (qemuProcessAttach): Likewise.
* src/qemu/qemu_process.h (qemuProcessAttach): Likewise.
* src/uml/uml_driver.c (umlGetProcessInfo): Likewise.
* src/util/virnetdev.h (virNetDevSetNamespace): Likewise.
* src/util/virnetdev.c (virNetDevSetNamespace): Likewise.
* tests/testutils.c (virtTestCaptureProgramOutput): Likewise.
* src/conf/storage_conf.h (_virStoragePerms): Use mode_t, uid_t,
and gid_t rather than int.
* src/security/security_dac.c (virSecurityDACSetOwnership): Likewise.
* src/conf/storage_conf.c (virStorageDefParsePerms): Avoid
compiler warning.
2012-03-02 06:57:43 -07:00
D. Herrendoerfer
e3ba402581 util: Add netlink event handling to virnetlink.c
This code adds a netlink event interface to libvirt.
It is based upon the event_poll code and makes use of
it. An event is generated for each netlink message sent
to the libvirt pid.

Signed-off-by: D. Herrendoerfer <d.herrendoerfer@herrendoerfer.name>
2012-02-29 10:37:24 -05:00
Jiri Denemark
8ab785783f hooks: Add support for capturing hook output
Hooks may now be used as filters.
2012-02-29 12:27:12 +01:00
Eric Blake
e957b67061 daemon: clean up daemonization
Valgrind detected a pipe fd leak before the parent exits on success,
introduced in commit 4296cea; by itself, the leak is not bad, since
we immediately called _exit(), but we might as well be clean to make
valgrind analysis easier.  Meanwhile, if the daemon grandchild detects
an error, the parent failed to flush the error message before exiting.
Also, we had the possibility of both parent and child returning to the
caller, such that the user could see duplicated reports of failure
from the two return paths.  And we might as well be robust to the
(unlikely) situation of being started with stdin closed.

* daemon/libvirtd.c (daemonForkIntoBackground): Use exit if an
error message was generated, avoid fd leaks for valgrind's sake,
avoid returning to caller in both parent and child, and don't
close a just-dup'd stdin.
Based on a report by Alex Jia.

* How to reproduce?
  % service libvirtd stop
  % valgrind -v --track-fds=yes /usr/sbin/libvirtd --daemon

* Actual valgrind result:

==16804== FILE DESCRIPTORS: 7 open at exit.
==16804== Open file descriptor 7:
==16804==    at 0x321FAD8B87: pipe (in /lib64/libc-2.12.so)
==16804==    by 0x41F34D: daemonForkIntoBackground (libvirtd.c:186)
==16804==    by 0x4207A0: main (libvirtd.c:1420)

Signed-off-by: Alex Jia <ajia@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
2011-12-28 05:14:38 -07:00
Jiri Denemark
f4324e3292 Implement keepalive protocol in libvirt daemon 2011-11-24 11:44:08 +01:00
Eric Blake
69d044c034 waitpid: improve safety
Based on a report by Coverity.  waitpid() can leak resources if it
fails with EINTR, so it should never be used without checking return
status.  But we already have a helper function that does that, so
use it in more places.

* src/lxc/lxc_container.c (lxcContainerAvailable): Use safer
virWaitPid.
* daemon/libvirtd.c (daemonForkIntoBackground): Likewise.
* tests/testutils.c (virtTestCaptureProgramOutput, virtTestMain):
Likewise.
* src/libvirt.c (virConnectAuthGainPolkit): Simplify with virCommand.
2011-10-24 15:42:52 -06:00
Osier Yang
33b55fd85a daemon: Always advertise libvirtd service
This is a regression introduced by new RPC codes, previously
we advertise the service via ssh even if the daemon doesn't
listen on TLS port (TCP is not choosed). Now the service is
only advertised when it listens on TLS or TCP port. This breaks
upper layer apps which intends to discover the service, such
as virt-manager.
2011-10-12 20:37:05 +08:00