From cefa695c578000765b0bd795cb7a332d31c6509b Mon Sep 17 00:00:00 2001 Message-Id: <cefa695c578000765b0bd795cb7a332d31c6509b.1305127059.git.jdenemar@redhat.com> From: Eric Blake <eblake@redhat.com> Date: Mon, 9 May 2011 17:22:13 -0600 Subject: [PATCH] Add a sysinfo util module and read host info API https://bugzilla.redhat.com/show_bug.cgi?id=661365 Move existing routines about virSysinfoDef to an util module, add a new entry point virSysinfoRead() to read the host values with dmidecode * src/conf/domain_conf.c src/conf/domain_conf.h src/util/sysinfo.c src/util/sysinfo.h: move to a new module, add virSysinfoRead() * src/Makefile.am: handle the new module build * src/libvirt_private.syms: new internal symbols * include/libvirt/virterror.h src/util/virterror.c: defined a new error code for that module * po/POTFILES.in: add new file for translations (cherry picked from commit 778c0976c0642313ea60b2861b6dba0c06b49f00) Conflicts: include/libvirt/virterror.h - number the addition src/conf/domain_conf.h - context proxy/Makefile.am - proxy is dead src/util/sysinfo.c - drop checks for PROXY --- include/libvirt/virterror.h | 3 +- po/POTFILES.in | 1 + proxy/Makefile.am | 1 + src/Makefile.am | 1 + src/conf/domain_conf.c | 19 ---- src/conf/domain_conf.h | 25 +----- src/libvirt_private.syms | 5 + src/util/sysinfo.c | 236 +++++++++++++++++++++++++++++++++++++++++++ src/util/sysinfo.h | 58 +++++++++++ src/util/virterror.c | 3 + 10 files changed, 308 insertions(+), 44 deletions(-) create mode 100644 src/util/sysinfo.c create mode 100644 src/util/sysinfo.h diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 8779a9b..c62c5eb 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -75,7 +75,8 @@ typedef enum { VIR_FROM_NWFILTER = 33, /* Error from network filter driver */ VIR_FROM_HOOK = 34, /* Error from Synchronous hooks */ VIR_FROM_DOMAIN_SNAPSHOT = 35,/* Error from domain snapshot */ - VIR_FROM_AUDIT = 36 /* Error from auditing subsystem */ + VIR_FROM_AUDIT = 36, /* Error from auditing subsystem */ + VIR_FROM_SYSINFO = 37, /* Error from sysinfo/SMBIOS */ } virErrorDomain; diff --git a/po/POTFILES.in b/po/POTFILES.in index 036f7a0..434dfc0 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -86,6 +86,7 @@ src/util/pci.c src/util/processinfo.c src/util/stats_linux.c src/util/storage_file.c +src/util/sysinfo.c src/util/util.c src/util/virtaudit.c src/util/virterror.c diff --git a/proxy/Makefile.am b/proxy/Makefile.am index 4716683..4b9ab11 100644 --- a/proxy/Makefile.am +++ b/proxy/Makefile.am @@ -19,6 +19,7 @@ libvirt_proxy_SOURCES = libvirt_proxy.c \ @top_srcdir@/src/util/logging.c \ @top_srcdir@/src/util/memory.c \ @top_srcdir@/src/util/network.c \ + @top_srcdir@/src/util/sysinfo.c \ @top_srcdir@/src/util/threads.c \ @top_srcdir@/src/util/util.c \ @top_srcdir@/src/util/uuid.c \ diff --git a/src/Makefile.am b/src/Makefile.am index dbb1bad..f8f1354 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -73,6 +73,7 @@ UTIL_SOURCES = \ util/qparams.c util/qparams.h \ util/stats_linux.c util/stats_linux.h \ util/storage_file.c util/storage_file.h \ + util/sysinfo.c util/sysinfo.h \ util/threads.c util/threads.h \ util/threads-pthread.h \ util/threads-win32.h \ diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index eebc504..944b623 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -666,25 +666,6 @@ virDomainClockDefClear(virDomainClockDefPtr def) VIR_FREE(def->timers); } -static void virSysinfoDefFree(virSysinfoDefPtr def) -{ - if (def == NULL) - return; - - VIR_FREE(def->bios_vendor); - VIR_FREE(def->bios_version); - VIR_FREE(def->bios_date); - VIR_FREE(def->bios_release); - - VIR_FREE(def->system_manufacturer); - VIR_FREE(def->system_product); - VIR_FREE(def->system_version); - VIR_FREE(def->system_serial); - VIR_FREE(def->system_uuid); - VIR_FREE(def->system_sku); - VIR_FREE(def); -} - void virDomainDefFree(virDomainDefPtr def) { unsigned int i; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 5a48231..e783a24 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -39,6 +39,7 @@ # include "nwfilter_params.h" # include "nwfilter_conf.h" # include "macvtap.h" +# include "sysinfo.h" /* Private component of virDomainXMLFlags */ typedef enum { @@ -561,30 +562,6 @@ struct _virDomainHostdevDef { }; -enum virDomainSysinfoType { - VIR_DOMAIN_SYSINFO_SMBIOS, - - VIR_DOMAIN_SYSINFO_LAST -}; - -typedef struct _virSysinfoDef virSysinfoDef; -typedef virSysinfoDef *virSysinfoDefPtr; -struct _virSysinfoDef { - int type; - - char *bios_vendor; - char *bios_version; - char *bios_date; - char *bios_release; - - char *system_manufacturer; - char *system_product; - char *system_version; - char *system_serial; - char *system_uuid; - char *system_sku; -}; - enum virDomainSmbiosMode { VIR_DOMAIN_SMBIOS_NONE, VIR_DOMAIN_SMBIOS_EMULATE, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 918190b..186c67c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -663,6 +663,11 @@ virStorageFileGetMetadata; virStorageFileGetMetadataFromFD; virStorageFileIsSharedFS; +# sysinfo.h +virSysinfoDefFree; +virSysinfoRead; + + # threads.h virMutexInit; virMutexInitRecursive; diff --git a/src/util/sysinfo.c b/src/util/sysinfo.c new file mode 100644 index 0000000..306125b --- /dev/null +++ b/src/util/sysinfo.c @@ -0,0 +1,236 @@ +/* + * sysinfo.c: get SMBIOS/sysinfo information from the host + * + * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010 Daniel Veillard + * + * 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 + * + * Author: Daniel Veillard <veillard@redhat.com> + */ + +#include <config.h> + +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> + +#include "virterror_internal.h" +#include "sysinfo.h" +#include "util.h" +#include "conf/domain_conf.h" +#include "logging.h" +#include "memory.h" + +#define VIR_FROM_THIS VIR_FROM_SYSINFO + +#define virSmbiosReportError(code, ...) \ + virReportErrorHelper(NULL, VIR_FROM_SYSINFO, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + +#define SYSINFO_SMBIOS_DECODER "dmidecode" + +/** + * virSysinfoDefFree: + * @def: a sysinfo structure + * + * Free up the sysinfo structure + */ + +void virSysinfoDefFree(virSysinfoDefPtr def) +{ + if (def == NULL) + return; + + VIR_FREE(def->bios_vendor); + VIR_FREE(def->bios_version); + VIR_FREE(def->bios_date); + VIR_FREE(def->bios_release); + + VIR_FREE(def->system_manufacturer); + VIR_FREE(def->system_product); + VIR_FREE(def->system_version); + VIR_FREE(def->system_serial); + VIR_FREE(def->system_uuid); + VIR_FREE(def->system_sku); + VIR_FREE(def); +} + +/** + * virSysinfoRead: + * + * Tries to read the SMBIOS information from the current host + * + * Returns: a filled up sysinfo structure or NULL in case of error + */ +#if defined WIN32 || defined PROXY +virSysinfoDefPtr +virSysinfoRead(void) { + /* + * this can probably be extracted from Windows using API or registry + * http://www.microsoft.com/whdc/system/platform/firmware/SMBIOS.mspx + */ + virReportSystemError(ENOSYS, "%s", + _("Host sysinfo extraction not supported on this platform")); + return(NULL); +} +#else +virSysinfoDefPtr +virSysinfoRead(void) { + char *path, *cur, *eol, *base; + int pid, outfd = -1, errfd = -1; + virSysinfoDefPtr ret = NULL; + const char *argv[] = { NULL, "-q", "-t", "0,1", NULL }; + int res, waitret, exitstatus; + char *outbuf = NULL; + char *errbuf = NULL; + + path = virFindFileInPath(SYSINFO_SMBIOS_DECODER); + if (path == NULL) { + virSmbiosReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to find path for %s binary"), + SYSINFO_SMBIOS_DECODER); + return(NULL); + } + argv[0] = path; + + res = virExec(argv, NULL, NULL, &pid, -1, &outfd, &errfd, + VIR_EXEC_NONE | VIR_EXEC_NONBLOCK); + if (res < 0) { + virSmbiosReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to execute command %s"), + path); + res = 1; + goto cleanup; + } + + /* + * we are interested in the output, capture it and errors too + */ + if (virPipeReadUntilEOF(outfd, errfd, &outbuf, &errbuf) < 0) { + virReportSystemError(errno, _("cannot wait for '%s'"), path); + while (waitpid(pid, &exitstatus, 0) == -1 && errno == EINTR) + ; + goto cleanup; + } + + if (outbuf) + VIR_DEBUG("Command stdout: %s", outbuf); + if (errbuf) + VIR_DEBUG("Command stderr: %s", errbuf); + + while ((waitret = waitpid(pid, &exitstatus, 0) == -1) && + (errno == EINTR)); + if (waitret == -1) { + virReportSystemError(errno, _("Failed to wait for '%s'"), path); + goto cleanup; + } + if (exitstatus != 0) { + virSmbiosReportError(VIR_ERR_INTERNAL_ERROR, + _("command %s failed with error code %d:%s"), + path, exitstatus, errbuf); + goto cleanup; + } + + if (VIR_ALLOC(ret) < 0) + goto no_memory; + + ret->type = VIR_DOMAIN_SYSINFO_SMBIOS; + + base = outbuf; + + if ((cur = strstr(base, "Vendor: ")) != NULL) { + cur += 8; + eol = strchr(cur, '\n'); + if ((eol) && ((ret->bios_vendor = strndup(cur, eol - cur)) == NULL)) + goto no_memory; + } + if ((cur = strstr(base, "Version: ")) != NULL) { + cur += 9; + eol = strchr(cur, '\n'); + if ((eol) && ((ret->bios_version = strndup(cur, eol - cur)) == NULL)) + goto no_memory; + } + if ((cur = strstr(base, "Release Date: ")) != NULL) { + cur += 14; + eol = strchr(cur, '\n'); + if ((eol) && ((ret->bios_date = strndup(cur, eol - cur)) == NULL)) + goto no_memory; + } + if ((cur = strstr(base, "BIOS Revision: ")) != NULL) { + cur += 15; + eol = strchr(cur, '\n'); + if ((eol) && ((ret->bios_release = strndup(cur, eol - cur)) == NULL)) + goto no_memory; + } + if ((base = strstr(outbuf, "System Information")) == NULL) + goto cleanup; + if ((cur = strstr(base, "Manufacturer: ")) != NULL) { + cur += 14; + eol = strchr(cur, '\n'); + if ((eol) && + ((ret->system_manufacturer = strndup(cur, eol - cur)) == NULL)) + goto no_memory; + } + if ((cur = strstr(base, "Product Name: ")) != NULL) { + cur += 14; + eol = strchr(cur, '\n'); + if ((eol) && ((ret->system_product = strndup(cur, eol - cur)) == NULL)) + goto no_memory; + } + if ((cur = strstr(base, "Version: ")) != NULL) { + cur += 9; + eol = strchr(cur, '\n'); + if ((eol) && ((ret->system_version = strndup(cur, eol - cur)) == NULL)) + goto no_memory; + } + if ((cur = strstr(base, "Serial Number: ")) != NULL) { + cur += 15; + eol = strchr(cur, '\n'); + if ((eol) && ((ret->system_serial = strndup(cur, eol - cur)) == NULL)) + goto no_memory; + } + if ((cur = strstr(base, "UUID: ")) != NULL) { + cur += 6; + eol = strchr(cur, '\n'); + if ((eol) && ((ret->system_uuid = strndup(cur, eol - cur)) == NULL)) + goto no_memory; + } + if ((cur = strstr(base, "SKU Number: ")) != NULL) { + cur += 12; + eol = strchr(cur, '\n'); + if ((eol) && ((ret->system_sku = strndup(cur, eol - cur)) == NULL)) + goto no_memory; + } + +cleanup: + VIR_FREE(outbuf); + VIR_FREE(errbuf); + VIR_FREE(path); + + return(ret); + +no_memory: + virReportOOMError(); + + + virSysinfoDefFree(ret); + ret = NULL; + goto cleanup; +} +#endif diff --git a/src/util/sysinfo.h b/src/util/sysinfo.h new file mode 100644 index 0000000..611d54e --- /dev/null +++ b/src/util/sysinfo.h @@ -0,0 +1,58 @@ +/* + * sysinfo.h: structure and entry points for sysinfo support + * + * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010 Daniel Veillard + * + * 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 + * + * Author: Daniel Veillard <veillard@redhat.com> + */ + +#ifndef __VIR_SYSINFOS_H__ +# define __VIR_SYSINFOS_H__ + +# include "internal.h" +# include "util.h" + +enum virDomainSysinfoType { + VIR_DOMAIN_SYSINFO_SMBIOS, + + VIR_DOMAIN_SYSINFO_LAST +}; + +typedef struct _virSysinfoDef virSysinfoDef; +typedef virSysinfoDef *virSysinfoDefPtr; +struct _virSysinfoDef { + int type; + + char *bios_vendor; + char *bios_version; + char *bios_date; + char *bios_release; + + char *system_manufacturer; + char *system_product; + char *system_version; + char *system_serial; + char *system_uuid; + char *system_sku; +}; + +virSysinfoDefPtr virSysinfoRead(void); + +void virSysinfoDefFree(virSysinfoDefPtr def); + +#endif /* __VIR_SYSINFOS_H__ */ diff --git a/src/util/virterror.c b/src/util/virterror.c index 70749a7..257e5ef 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -190,6 +190,9 @@ static const char *virErrorDomainName(virErrorDomain domain) { case VIR_FROM_AUDIT: dom = "Audit"; break; + case VIR_FROM_SYSINFO: + dom = "Sysinfo"; + break; } return(dom); } -- 1.7.5.rc3