From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> 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. In version 2: - Add to RPM specs - Add man page - Use getopt to parse --help, --version & --quiet options - Don't use VT100 escape codes unless on a tty - Disable QEMU / LXC checks if not compiled into libvirt --- tools/Makefile.am | 33 ++++++- tools/virt-host-validate-common.c | 214 +++++++++++++++++++++++++++++++++++++ tools/virt-host-validate-common.h | 57 ++++++++++ tools/virt-host-validate-lxc.c | 37 +++++++ tools/virt-host-validate-lxc.h | 27 +++++ tools/virt-host-validate-qemu.c | 52 +++++++++ tools/virt-host-validate-qemu.h | 27 +++++ tools/virt-host-validate.c | 213 ++++++++++++++++++++++++++++++++++++ 8 files changed, 658 insertions(+), 2 deletions(-) create mode 100644 tools/virt-host-validate-common.c create mode 100644 tools/virt-host-validate-common.h create mode 100644 tools/virt-host-validate-lxc.c create mode 100644 tools/virt-host-validate-lxc.h create mode 100644 tools/virt-host-validate-qemu.c create mode 100644 tools/virt-host-validate-qemu.h create mode 100644 tools/virt-host-validate.c diff --git a/tools/Makefile.am b/tools/Makefile.am index 6705546..6596a51 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -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 diff --git a/tools/virt-host-validate-common.c b/tools/virt-host-validate-common.c new file mode 100644 index 0000000..e8cff85 --- /dev/null +++ b/tools/virt-host-validate-common.c @@ -0,0 +1,214 @@ +/* + * 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; +} + + +int virHostValidateHasCPUFlag(const char *name) +{ + FILE *fp = fopen("/proc/cpuinfo", "r"); + int ret = 0; + + if (!fp) + return 0; + + do { + char line[1024]; + + if (!fgets(line, sizeof(line), fp)) + break; + + if (strstr(line, name)) { + ret = 1; + break; + } + } while (1); + + VIR_FORCE_FCLOSE(fp); + + return ret; +} + + +int virHostValidateLinuxKernel(const char *hvname, + int version, + virHostValidateLevel level, + const char *hint) +{ + struct utsname uts; + int major, minor, micro; + 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; + } + + micro = (thisversion & 0xff); + minor = ((thisversion >> 8) & 0xff); + major = ((thisversion >> 16) & 0xff); + + if (major > ((version >> 16) & 0xff)) { + virHostMsgPass(); + return 0; + } else if (major < ((version >> 16) & 0xff)) { + virHostMsgFail(level, hint); + return -1; + } + + if (minor > ((version >> 8) & 0xff)) { + virHostMsgPass(); + return 0; + } else if (minor < ((version >> 8) & 0xff)) { + virHostMsgFail(level, hint); + return -1; + } + + if (micro > (version & 0xff)) { + virHostMsgPass(); + return 0; + } else if (micro < (version & 0xff)) { + virHostMsgFail(level, hint); + return -1; + } + + virHostMsgPass(); + return 0; +} diff --git a/tools/virt-host-validate-common.h b/tools/virt-host-validate-common.h new file mode 100644 index 0000000..99b09b6 --- /dev/null +++ b/tools/virt-host-validate-common.h @@ -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 int virHostValidateHasCPUFlag(const char *name); + +extern int virHostValidateLinuxKernel(const char *hvname, + int version, + virHostValidateLevel level, + const char *hint); + +#endif /* __VIRT_HOST_VALIDATE_COMMON_H__ */ diff --git a/tools/virt-host-validate-lxc.c b/tools/virt-host-validate-lxc.c new file mode 100644 index 0000000..9d69b67 --- /dev/null +++ b/tools/virt-host-validate-lxc.c @@ -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; +} diff --git a/tools/virt-host-validate-lxc.h b/tools/virt-host-validate-lxc.h new file mode 100644 index 0000000..ef824be --- /dev/null +++ b/tools/virt-host-validate-lxc.h @@ -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__ */ diff --git a/tools/virt-host-validate-qemu.c b/tools/virt-host-validate-qemu.c new file mode 100644 index 0000000..d3a82cc --- /dev/null +++ b/tools/virt-host-validate-qemu.c @@ -0,0 +1,52 @@ +/* + * 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; + + if (virHostValidateHasCPUFlag("svm") || + virHostValidateHasCPUFlag("vmx")) { + 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; + } + + 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; +} diff --git a/tools/virt-host-validate-qemu.h b/tools/virt-host-validate-qemu.h new file mode 100644 index 0000000..3e79d51 --- /dev/null +++ b/tools/virt-host-validate-qemu.h @@ -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__ */ diff --git a/tools/virt-host-validate.c b/tools/virt-host-validate.c new file mode 100644 index 0000000..06fee58 --- /dev/null +++ b/tools/virt-host-validate.c @@ -0,0 +1,213 @@ +/* + * 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; + + 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")) && + virHostValidateQEMU() < 0) + ret = EXIT_FAILURE; +#endif + +#if WITH_LXC + if ((!hvname || STREQ(hvname, "lxc")) && + virHostValidateLXC() < 0) + ret = EXIT_FAILURE; +#endif + + 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 + +*/ -- 1.7.7.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list