Add a virt-host-validate command to sanity check HV config

To assist people in verifying that their host is operating in an
optimal manner, provide a 'virt-host-validate' command. For each
type of hypervisor, it will check any pre-requisites, or other
good recommendations and report what's working & what is not.

eg

  # virt-host-validate
  QEMU: Checking for device /dev/kvm                                         : FAIL (Check that the 'kvm-intel' or 'kvm-amd' modules are loaded & the BIOS has enabled virtualization)
  QEMU: Checking for device /dev/vhost                                       : WARN (Load the 'vhost_net' module to improve performance of virtio networking)
  QEMU: Checking for device /dev/net/tun                                     : PASS
   LXC: Checking for Linux >= 2.6.26                                         : PASS

This warns people if they have vmx/svm, but don't have /dev/kvm. It
also warns about missing /dev/vhost net.
This commit is contained in:
Daniel P. Berrange 2012-01-10 17:31:21 +00:00
parent b66d1bef14
commit 54a38915d8
11 changed files with 657 additions and 2 deletions

View File

@ -1198,9 +1198,11 @@ rm -f $RPM_BUILD_ROOT%{_sysconfdir}/sysctl.d/libvirtd
%{_mandir}/man1/virsh.1*
%{_mandir}/man1/virt-xml-validate.1*
%{_mandir}/man1/virt-pki-validate.1*
%{_mandir}/man1/virt-host-validate.1*
%{_bindir}/virsh
%{_bindir}/virt-xml-validate
%{_bindir}/virt-pki-validate
%{_bindir}/virt-host-validate
%{_libdir}/lib*.so.*
%dir %{_datadir}/libvirt/

View File

@ -147,6 +147,7 @@ rm -rf $RPM_BUILD_ROOT
%{_mingw32_bindir}/virsh.exe
%{_mingw32_bindir}/virt-xml-validate
%{_mingw32_bindir}/virt-pki-validate
%{_mingw32_bindir}/virt-host-validate.exe
%{_mingw32_bindir}/libvirt-qemu-0.dll
%{_mingw32_libdir}/libvirt.dll.a

View File

@ -159,3 +159,7 @@ src/xenxs/xen_xm.c
tools/console.c
tools/libvirt-guests.init.sh
tools/virsh.c
tools/virt-host-validate-common.c
tools/virt-host-validate-lxc.c
tools/virt-host-validate-qemu.c
tools/virt-host-validate.c

View File

@ -30,14 +30,18 @@ EXTRA_DIST = \
DISTCLEANFILES =
bin_SCRIPTS = virt-xml-validate virt-pki-validate
bin_PROGRAMS = virsh
bin_PROGRAMS = virsh virt-host-validate
if HAVE_SANLOCK
sbin_SCRIPTS = virt-sanlock-cleanup
DISTCLEANFILES += virt-sanlock-cleanup
endif
dist_man1_MANS = virt-xml-validate.1 virt-pki-validate.1 virsh.1
dist_man1_MANS = \
virt-host-validate.1 \
virt-pki-validate.1 \
virt-xml-validate.1 \
virsh.1
if HAVE_SANLOCK
dist_man8_MANS = virt-sanlock-cleanup.8
endif
@ -56,6 +60,9 @@ virt-pki-validate: virt-pki-validate.in Makefile
virt-pki-validate.1: virt-pki-validate.in
$(AM_V_GEN)$(POD2MAN) $< $(srcdir)/$@
virt-host-validate.1: virt-host-validate.c
$(AM_V_GEN)$(POD2MAN) $< $(srcdir)/$@
virt-sanlock-cleanup: virt-sanlock-cleanup.in Makefile
$(AM_V_GEN)sed -e 's,[@]SYSCONFDIR@,$(sysconfdir),' \
-e 's,[@]LOCALSTATEDIR@,$(localstatedir),' < $< > $@ \
@ -64,6 +71,28 @@ virt-sanlock-cleanup: virt-sanlock-cleanup.in Makefile
virt-sanlock-cleanup.8: virt-sanlock-cleanup.in
$(AM_V_GEN)$(POD2MAN) $< $(srcdir)/$@
virt_host_validate_SOURCES = \
virt-host-validate.c \
virt-host-validate-common.c virt-host-validate-common.h \
virt-host-validate-qemu.c virt-host-validate-qemu.h \
virt-host-validate-lxc.c virt-host-validate-lxc.h \
$(NULL)
virt_host_validate_LDFLAGS = \
$(WARN_LDFLAGS) \
$(COVERAGE_LDFLAGS) \
$(NULL)
virt_host_validate_LDADD = \
../src/libvirt.la \
../gnulib/lib/libgnu.la \
$(NULL)
virt_host_validate_CFLAGS = \
$(WARN_CFLAGS) \
$(COVERAGE_CFLAGS) \
$(NULL)
virsh_SOURCES = \
console.c console.h \
virsh.c

View File

@ -0,0 +1,190 @@
/*
* virt-host-validate-common.c: Sanity check helper APIs
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <config.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/utsname.h>
#include "util.h"
#include "memory.h"
#include "virfile.h"
#include "virt-host-validate-common.h"
static bool quiet;
void virHostMsgSetQuiet(bool quietFlag)
{
quiet = quietFlag;
}
void virHostMsgCheck(const char *prefix,
const char *format,
...)
{
va_list args;
char *msg;
if (quiet)
return;
va_start(args, format);
if (virVasprintf(&msg, format, args) < 0) {
perror("malloc");
abort();
}
va_end(args);
fprintf(stdout, _("%6s: Checking %-60s: "), prefix, msg);
VIR_FREE(msg);
}
static bool virHostMsgWantEscape(void)
{
static bool detectTty = true;
static bool wantEscape = false;
if (detectTty) {
if (isatty(STDOUT_FILENO))
wantEscape = true;
detectTty = false;
}
return wantEscape;
}
void virHostMsgPass(void)
{
if (quiet)
return;
if (virHostMsgWantEscape())
fprintf(stdout, "\033[32m%s\033[0m\n", _("PASS"));
else
fprintf(stdout, "%s\n", _("PASS"));
}
static const char * failMessages[] = {
N_("FAIL"),
N_("WARN"),
N_("NOTE"),
};
verify(ARRAY_CARDINALITY(failMessages) == VIR_HOST_VALIDATE_LAST);
static const char *failEscapeCodes[] = {
"\033[31m",
"\033[33m",
"\033[34m",
};
verify(ARRAY_CARDINALITY(failEscapeCodes) == VIR_HOST_VALIDATE_LAST);
void virHostMsgFail(virHostValidateLevel level,
const char *hint)
{
if (virHostMsgWantEscape())
fprintf(stdout, "%s%s\033[0m (%s)\n",
failEscapeCodes[level], _(failMessages[level]), hint);
else
fprintf(stdout, "%s (%s)\n",
_(failMessages[level]), hint);
}
int virHostValidateDevice(const char *hvname,
const char *devname,
virHostValidateLevel level,
const char *hint)
{
virHostMsgCheck(hvname, "for device %s", devname);
if (access(devname, R_OK|W_OK) < 0) {
virHostMsgFail(level, hint);
return -1;
}
virHostMsgPass();
return 0;
}
bool virHostValidateHasCPUFlag(const char *name)
{
FILE *fp = fopen("/proc/cpuinfo", "r");
bool ret = false;
if (!fp)
return false;
do {
char line[1024];
if (!fgets(line, sizeof(line), fp))
break;
if (strstr(line, name)) {
ret = true;
break;
}
} while (1);
VIR_FORCE_FCLOSE(fp);
return ret;
}
int virHostValidateLinuxKernel(const char *hvname,
int version,
virHostValidateLevel level,
const char *hint)
{
struct utsname uts;
unsigned long thisversion;
uname(&uts);
virHostMsgCheck(hvname, _("for Linux >= %d.%d.%d"),
((version >> 16) & 0xff),
((version >> 8) & 0xff),
(version & 0xff));
if (STRNEQ(uts.sysname, "Linux")) {
virHostMsgFail(level, hint);
return -1;
}
if (virParseVersionString(uts.release, &thisversion, true) < 0) {
virHostMsgFail(level, hint);
return -1;
}
if (thisversion < version) {
virHostMsgFail(level, hint);
return -1;
} else {
virHostMsgPass();
return 0;
}
}

View File

@ -0,0 +1,57 @@
/*
* virt-host-validate-common.h: Sanity check helper APIs
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __VIRT_HOST_VALIDATE_COMMON_H__
# define __VIRT_HOST_VALIDATE_COMMON_H__
# include "internal.h"
typedef enum {
VIR_HOST_VALIDATE_FAIL,
VIR_HOST_VALIDATE_WARN,
VIR_HOST_VALIDATE_NOTE,
VIR_HOST_VALIDATE_LAST,
} virHostValidateLevel;
extern void virHostMsgSetQuiet(bool quietFlag);
extern void virHostMsgCheck(const char *prefix,
const char *format,
...) ATTRIBUTE_FMT_PRINTF(2, 3);
extern void virHostMsgPass(void);
extern void virHostMsgFail(virHostValidateLevel level,
const char *hint);
extern int virHostValidateDevice(const char *hvname,
const char *devname,
virHostValidateLevel level,
const char *hint);
extern bool virHostValidateHasCPUFlag(const char *name);
extern int virHostValidateLinuxKernel(const char *hvname,
int version,
virHostValidateLevel level,
const char *hint);
#endif /* __VIRT_HOST_VALIDATE_COMMON_H__ */

View File

@ -0,0 +1,37 @@
/*
* virt-host-validate-lxc.c: Sanity check a LXC hypervisor host
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <config.h>
#include "virt-host-validate-lxc.h"
#include "virt-host-validate-common.h"
int virHostValidateLXC(void)
{
int ret = 0;
if (virHostValidateLinuxKernel("LXC", (2 << 16) | (6 << 8) | 26,
VIR_HOST_VALIDATE_FAIL,
_("Upgrade to a kernel supporting namespaces")) < 0)
ret = -1;
return ret;
}

View File

@ -0,0 +1,27 @@
/*
* virt-host-validate-lxc.h: Sanity check a LXC hypervisor host
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __VIRT_HOST_VALIDATE_LXC_H__
# define __VIRT_HOST_VALIDATE_LXC_H__
extern int virHostValidateLXC(void);
#endif /* __VIRT_HOST_VALIDATE_LXC_H__ */

View File

@ -0,0 +1,57 @@
/*
* virt-host-validate-qemu.c: Sanity check a QEMU hypervisor host
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <config.h>
#include "virt-host-validate-qemu.h"
#include "virt-host-validate-common.h"
int virHostValidateQEMU(void)
{
int ret = 0;
virHostMsgCheck("QEMU", "%s", ("for hardware virtualization"));
if (virHostValidateHasCPUFlag("svm") ||
virHostValidateHasCPUFlag("vmx")) {
virHostMsgPass();
if (virHostValidateDevice("QEMU", "/dev/kvm",
VIR_HOST_VALIDATE_FAIL,
_("Check that the 'kvm-intel' or 'kvm-amd' modules are "
"loaded & the BIOS has enabled virtualization")) < 0)
ret = -1;
} else {
virHostMsgFail(VIR_HOST_VALIDATE_WARN,
_("Only emulated CPUs are available, performance will be significantly limited"));
}
if (virHostValidateDevice("QEMU", "/dev/vhost-net",
VIR_HOST_VALIDATE_WARN,
_("Load the 'vhost_net' module to improve performance "
"of virtio networking")) < 0)
ret = -1;
if (virHostValidateDevice("QEMU", "/dev/net/tun",
VIR_HOST_VALIDATE_FAIL,
_("Load the 'tun' module to enable networking for QEMU guests")) < 0)
ret = -1;
return ret;
}

View File

@ -0,0 +1,27 @@
/*
* virt-host-validate-qemu.h: Sanity check a QEMU hypervisor host
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __VIRT_HOST_VALIDATE_QEMU_H__
# define __VIRT_HOST_VALIDATE_QEMU_H__
extern int virHostValidateQEMU(void);
#endif /* __VIRT_HOST_VALIDATE_QEMU_H__ */

224
tools/virt-host-validate.c Normal file
View File

@ -0,0 +1,224 @@
/*
* virt-host-check.c: Sanity check a hypervisor host
*
* Copyright (C) 2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <gettext.h>
#include <getopt.h>
#include "internal.h"
#include "configmake.h"
#include "virt-host-validate-common.h"
#if WITH_QEMU
# include "virt-host-validate-qemu.h"
#endif
#if WITH_LXC
# include "virt-host-validate-lxc.h"
#endif
static void
show_help(FILE *out, const char *argv0)
{
fprintf(out,
_("\n"
"syntax: %s [OPTIONS] [HVTYPE]\n"
"\n"
" Hypervisor types:\n"
"\n"
" - qemu\n"
" - lxc\n"
"\n"
" Options:\n"
" -h, --help Display command line help\n"
" -v, --version Display command version\n"
" -q, --quiet Don't display progress information\n"
"\n"),
argv0);
}
static void
show_version(FILE *out, const char *argv0)
{
fprintf(out, "version: %s %s\n", argv0, VERSION);
}
static const struct option argOptions[] = {
{ "help", 0, NULL, 'h', },
{ "version", 0, NULL, 'v', },
{ "quiet", 0, NULL, 'q', },
{ NULL, 0, NULL, '\0', }
};
int
main(int argc, char **argv)
{
const char *hvname = NULL;
int c;
int ret = EXIT_SUCCESS;
bool quiet = false;
bool usedHvname = false;
if (!setlocale(LC_ALL, "")) {
perror("setlocale");
/* failure to setup locale is not fatal */
}
if (!bindtextdomain(PACKAGE, LOCALEDIR)) {
perror("bindtextdomain");
return EXIT_FAILURE;
}
if (!textdomain(PACKAGE)) {
perror("textdomain");
return EXIT_FAILURE;
}
while ((c = getopt_long(argc, argv, "hvq", argOptions, NULL)) != -1) {
switch (c) {
case 'v':
show_version(stdout, argv[0]);
return EXIT_SUCCESS;
case 'h':
show_help(stdout, argv[0]);
return EXIT_SUCCESS;
case 'q':
quiet = true;
break;
case '?':
default:
show_help(stderr, argv[0]);
return EXIT_FAILURE;
}
}
if ((argc-optind) > 2) {
fprintf(stderr, _("%s: too many command line arguments\n"), argv[0]);
show_help(stderr, argv[0]);
return EXIT_FAILURE;
}
if (argc > 1)
hvname = argv[optind];
virHostMsgSetQuiet(quiet);
#if WITH_QEMU
if (!hvname || STREQ(hvname, "qemu")) {
usedHvname = true;
if (virHostValidateQEMU() < 0)
ret = EXIT_FAILURE;
}
#endif
#if WITH_LXC
if (!hvname || STREQ(hvname, "lxc")) {
usedHvname = true;
if (virHostValidateLXC() < 0)
ret = EXIT_FAILURE;
}
#endif
if (hvname && !usedHvname) {
fprintf(stderr, _("%s: unsupported hypervisor name %s\n"),
argv[0], hvname);
return EXIT_FAILURE;
}
return ret;
}
/*
=pod
=head1 NAME
virt-host-validate - validate host virtualization setup
=head1 SYNOPSIS
virt-host-validate [OPTIONS...] [HV-TYPE]
=head1 DESCRIPTION
This tool validates that the host is configured in a suitable
way to run libvirt hypervisor drivers. If invoked without any
arguments it will check support for all hypervisor drivers it
is aware of. Optionally it can be given a particular hypervisor
type ('qemu' or 'lxc') to restrict the checks to those relevant
for that virtualization technology
=head1 OPTIONS
=over 4
=item C<-v>, C<--version>
Display the command version
=item C<-h>, C<--help>
Display the command line help
=item C<-q>, C<--quiet>
Don't display details of individual checks being performed.
Only display output if a check does not pass.
=back
=head1 EXIT STATUS
Upon successful validation, an exit status of 0 will be set. Upon
failure a non-zero status will be set.
=head1 AUTHOR
Daniel P. Berrange
=head1 BUGS
Report any bugs discovered to the libvirt community via the
mailing list C<http://libvirt.org/contact.html> or bug tracker C<http://libvirt.org/bugs.html>.
Alternatively report bugs to your software distributor / vendor.
=head1 COPYRIGHT
Copyright (C) 2012 by Red Hat, Inc.
=head1 LICENSE
virt-host-validate is distributed under the terms of the GNU GPL v2+.
This is free software; see the source for copying conditions. There
is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE
=head1 SEE ALSO
C<virsh(1)>, C<virt-pki-validate>, C<virt-xml-validate>
=cut
*/