From: VMware, Inc <> Date: Thu, 17 Jun 2010 21:35:14 +0000 (-0700) Subject: Add a "VMX logger" to Tools. X-Git-Tag: 2010.06.16-268169~100 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dd7503385a9a85cec8ac709d4e07c27bc96a4994;p=thirdparty%2Fopen-vm-tools.git Add a "VMX logger" to Tools. This logger using the "log" RPC to log to the host's vmware.log. It's useful when enabling file logging in the guest is not possible (such as for backup tests) or to make it easier to collect logs when debugging some VMX -> Tools interaction. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/docs/api/services/utils.txt b/open-vm-tools/docs/api/services/utils.txt index 3fb66488f..284c1172a 100644 --- a/open-vm-tools/docs/api/services/utils.txt +++ b/open-vm-tools/docs/api/services/utils.txt @@ -47,7 +47,7 @@ for each domain are: - Valid values: error, critical, warning, message, info, debug, none - This value is required when configuring a domain. - handler: the handler to use when logging. - - Valid values: std, outputdebugstring (Win32-only), file, file+ + - Valid values: std, outputdebugstring (Win32-only), file, file+, vmx (same as "file", but appends to existing log file), syslog (Unix only). - Default: "std" on Unix, "outputdebugstring" on Windows. @@ -68,6 +68,11 @@ When using syslog, the following options are available: LOG_USER. This option should be defined for the application's default log domain (it's ignored for all other domains). +The "vmx" logger will log all messages to the host; it's not recommended +for normal use, since writing to the host log is an expensive operation and +can also affect other running applications that need to send messages to the +host. Do not use this logger unless explicitly instructed to do so. + Logging configuration should be under the "[logging]" group in the application's configuration file. diff --git a/open-vm-tools/libvmtools/Makefile.am b/open-vm-tools/libvmtools/Makefile.am index 32702808a..fe06e049d 100644 --- a/open-vm-tools/libvmtools/Makefile.am +++ b/open-vm-tools/libvmtools/Makefile.am @@ -63,6 +63,7 @@ libvmtools_la_SOURCES += sysLogger.c libvmtools_la_SOURCES += vmtools.c libvmtools_la_SOURCES += vmtoolsConfig.c libvmtools_la_SOURCES += vmtoolsLog.c +libvmtools_la_SOURCES += vmxLogger.c # Recompile the rpcIn library with GLIB support. libvmtools_la_SOURCES += $(top_srcdir)/lib/rpcIn/rpcin.c diff --git a/open-vm-tools/libvmtools/vmtoolsInt.h b/open-vm-tools/libvmtools/vmtoolsInt.h index 1fefabe14..9b7cf4d86 100644 --- a/open-vm-tools/libvmtools/vmtoolsInt.h +++ b/open-vm-tools/libvmtools/vmtoolsInt.h @@ -25,6 +25,7 @@ * Internal definitions used by the vmtools library. */ +#include "vmware.h" #include "vmware/tools/utils.h" /* ************************************************************************** * @@ -106,5 +107,20 @@ VMSysLoggerConfig(const gchar *defaultDomain, GKeyFile *cfg); #endif +LogHandlerData * +VMXLoggerConfig(const gchar *defaultDomain, + const gchar *domain, + const gchar *name, + GKeyFile *cfg); + +/* ************************************************************************** * + * Miscelaneous. * + * ************************************************************************** */ + +gint +VMToolsAsprintf(gchar **string, + gchar const *format, + ...) PRINTF_DECL(2, 3); + #endif /* _VMTOOLSINT_H_ */ diff --git a/open-vm-tools/libvmtools/vmtoolsLog.c b/open-vm-tools/libvmtools/vmtoolsLog.c index dbec8b5d6..e15e95ae1 100644 --- a/open-vm-tools/libvmtools/vmtoolsLog.c +++ b/open-vm-tools/libvmtools/vmtoolsLog.c @@ -100,11 +100,12 @@ static LogHandler gHandlers[] = { { 0, "std", VMStdLoggerConfig }, { 1, "file", VMFileLoggerConfig }, { 2, "file+", VMFileLoggerConfig }, + { 3, "vmx", VMXLoggerConfig }, #if defined(_WIN32) - { 3, "outputdebugstring", VMDebugOutputConfig }, + { 4, "outputdebugstring", VMDebugOutputConfig }, { -1, NULL, VMDebugOutputConfig }, #else - { 3, "syslog", VMSysLoggerConfig }, + { 4, "syslog", VMSysLoggerConfig }, { -1, NULL, VMStdLoggerConfig }, #endif }; @@ -131,7 +132,7 @@ static GPtrArray *gDomains = NULL; * @return Number of bytes printed. */ -static INLINE gint +gint VMToolsAsprintf(gchar **string, gchar const *format, ...) diff --git a/open-vm-tools/libvmtools/vmxLogger.c b/open-vm-tools/libvmtools/vmxLogger.c new file mode 100644 index 000000000..6c5f4463f --- /dev/null +++ b/open-vm-tools/libvmtools/vmxLogger.c @@ -0,0 +1,143 @@ +/********************************************************* + * Copyright (C) 2010 VMware, Inc. All rights reserved. + * + * This program 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 version 2.1 and no later version. + * + * This program 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 Lesser GNU General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + *********************************************************/ + +/** + * @file vmxLogger.c + * + * A logger that writes the logs to the VMX log file. + */ + +#include "vmtoolsInt.h" +#include "vmware/tools/guestrpc.h" + +typedef struct VMXLoggerData { + LogHandlerData handler; + GStaticMutex lock; + RpcChannel *chan; +} VMXLoggerData; + + +/* + ******************************************************************************* + * VMXLoggerLog -- */ /** + * + * Logs a message to the VMX using the backdoor. + * + * The logger uses its own RpcChannel, opening and closing the channel for each + * log message sent. This is not optimal, especially if the application already + * has an RpcChannel instantiated; this could be fixed by providing a way for + * the application to provide its own RpcChannel to the logging code, if it uses + * one, so that this logger can re-use it. + * + * @param[in] domain Unused. + * @param[in] level Log level. + * @param[in] message Message to log. + * @param[in] _data VMX logger data. + * @param[in] errfn Unused. + * + * @return TRUE if successfully logged the message. + * + ******************************************************************************* + */ + +static gboolean +VMXLoggerLog(const gchar *domain, + GLogLevelFlags level, + const gchar *message, + LogHandlerData *_data, + LogErrorFn errfn) +{ + gboolean ret = FALSE; + VMXLoggerData *data = (VMXLoggerData *) _data; + + g_static_mutex_lock(&data->lock); + if (RpcChannel_Start(data->chan)) { + gchar *msg; + gint cnt = VMToolsAsprintf(&msg, "log %s", message); + + /* + * XXX: RpcChannel_Send() can log stuff in certain situations, which will + * cause this to blow up. Hopefully we won't hit those too often since + * we're stopping / starting the channel for each log message. + */ + ret = RpcChannel_Send(data->chan, msg, cnt, NULL, NULL); + + g_free(msg); + RpcChannel_Stop(data->chan); + } + g_static_mutex_unlock(&data->lock); + + return ret; +} + + +/* + ******************************************************************************* + * VMXLoggerDestroy -- */ /** + * + * Cleans up the internal state of a VMX logger. + * + * @param[in] _data VMX logger data. + * + ******************************************************************************* + */ + +static void +VMXLoggerDestroy(LogHandlerData *_data) +{ + VMXLoggerData *data = (VMXLoggerData *) _data; + RpcChannel_Destroy(data->chan); + g_static_mutex_free(&data->lock); + g_free(data); +} + + +/* + ******************************************************************************* + * VMXLoggerConfig -- */ /** + * + * Configures a new VMX logger. + * + * @param[in] defaultDomain Unused. + * @param[in] domain Unused. + * @param[in] name Unused. + * @param[in] cfg Unused. + * + * @return The VMX logger data. + * + ******************************************************************************* + */ + +LogHandlerData * +VMXLoggerConfig(const gchar *defaultDomain, + const gchar *domain, + const gchar *name, + GKeyFile *cfg) +{ + VMXLoggerData *data = g_new0(VMXLoggerData, 1); + data->handler.logfn = VMXLoggerLog; + data->handler.convertToLocal = FALSE; + data->handler.timestamp = FALSE; + data->handler.shared = TRUE; + data->handler.copyfn = NULL; + data->handler.dtor = VMXLoggerDestroy; + g_static_mutex_init(&data->lock); + data->chan = BackdoorChannel_New(); + return &data->handler; +} +