From a77a3130e22df54a775f3b5b084061fb7e4f18cd16abb71cbab1cc1f3967c5a7 Mon Sep 17 00:00:00 2001 From: Kirk Allan Date: Fri, 12 Oct 2018 21:07:33 +0000 Subject: [PATCH] Accepting request 641751 from home:kallan:branches:Virtualization:VMware - Added Handle Linux kernel /proc FS uint32 type stat overflow when calculating (bsc#1110793). + handle-linux-kernel-stat-overflow.patch On both 32-bit and 64-bit Linux, tools always parses Linux kernel /proc FS stats as uint64 values. For rate stats, current - previous can handle uint64 type stat overflow, but not uint32 type. - Added patch for Optional override for short and long OS names sent from Tools (bsc#1047469). + optional-override-os-name.patch Added support for customers to override the returned long and short OS names through the tools config file. If the setting is present, then names gathered by hostinfo will be ignored. The user is responsible for setting the appropriate names. - Added patch for Workaround for false negative result when detecting cloud-init existance (bsc#1111619) + false-negative-cloud-init.patch "cloud-init -v" cmd is used to detect if cloud-init is properly configured and it works on most linux distros. However in some linux distro like Amazon Linux 2, "cloud-init -v" will print result to stderr instead of stdout and it makes "forkExecAndWaitCommand" give false negative result. 1. added a new bool switch in "ForkExecAndWaitCommand" to choose if we should ignore the stderr output when the return code is 0 2. removed unnecessary reference for "ForkExecAndWaitCommand" in linuxDeploymentUtilities.c 3. trivial change for some formatting - Update to 10.2.5 (build 8068406) (boo#1089181) OBS-URL: https://build.opensuse.org/request/show/641751 OBS-URL: https://build.opensuse.org/package/show/Virtualization:VMware/open-vm-tools?expand=0&rev=362 --- false-negative-cloud-init.patch | 200 ++++++++++++++++++++++++ handle-linux-kernel-stat-overflow.patch | 35 +++++ open-vm-tools.changes | 31 +++- open-vm-tools.spec | 6 + optional-override-os-name.patch | 156 ++++++++++++++++++ 5 files changed, 427 insertions(+), 1 deletion(-) create mode 100644 false-negative-cloud-init.patch create mode 100644 handle-linux-kernel-stat-overflow.patch create mode 100644 optional-override-os-name.patch diff --git a/false-negative-cloud-init.patch b/false-negative-cloud-init.patch new file mode 100644 index 0000000..07c7bb9 --- /dev/null +++ b/false-negative-cloud-init.patch @@ -0,0 +1,200 @@ +commit 0a2d2f8baf9e4dccb2fd15c833efef5e704683ea +Author: Oliver Kurth +Date: Fri Jul 13 15:20:38 2018 -0700 + + Workaround for false negative result when detecting cloud-init existance + + "cloud-init -v" cmd is used to detect if cloud-init is properly configured and + it works on most linux distros. However in some linux distro like Amazon Linux 2, + "cloud-init -v" will print result to stderr instead of stdout and it makes + "forkExecAndWaitCommand" give false negative result. + + 1. added a new bool switch in "ForkExecAndWaitCommand" to choose + if we should ignore the stderr output when the return code is 0 + 2. removed unnecessary reference for "ForkExecAndWaitCommand" in linuxDeploymentUtilities.c + 3. trivial change for some formatting + +diff --git a/open-vm-tools/libDeployPkg/linuxDeployment.c b/open-vm-tools/libDeployPkg/linuxDeployment.c +index 996f184c..34c8b956 100644 +--- a/open-vm-tools/libDeployPkg/linuxDeployment.c ++++ b/open-vm-tools/libDeployPkg/linuxDeployment.c +@@ -139,7 +139,7 @@ static bool CopyFileToDirectory(const char* srcPath, const char* destPath, + const char* fileName); + static DeployPkgStatus Deploy(const char* pkgName); + static char** GetFormattedCommandLine(const char* command); +-int ForkExecAndWaitCommand(const char* command); ++int ForkExecAndWaitCommand(const char* command, bool ignoreStdErr); + static void SetDeployError(const char* format, ...); + static const char* GetDeployError(void); + static void NoLogging(int level, const char* fmtstr, ...); +@@ -920,7 +920,7 @@ CloudInitSetup(const char *tmpDirPath) + "/bin/mkdir -p %s", cloudInitTmpDirPath); + command[sizeof(command) - 1] = '\0'; + +- forkExecResult = ForkExecAndWaitCommand(command); ++ forkExecResult = ForkExecAndWaitCommand(command, false); + if (forkExecResult != 0) { + SetDeployError("Error creating %s dir: %s", + cloudInitTmpDirPath, +@@ -937,7 +937,7 @@ CloudInitSetup(const char *tmpDirPath) + "/usr/bin/test -f %s/nics.txt", tmpDirPath); + command[sizeof(command) - 1] = '\0'; + +- forkExecResult = ForkExecAndWaitCommand(command); ++ forkExecResult = ForkExecAndWaitCommand(command, false); + + /* + * /usr/bin/test -f returns 0 if the file exists +@@ -946,7 +946,7 @@ CloudInitSetup(const char *tmpDirPath) + */ + if (forkExecResult == 0) { + sLog(log_info, "nics.txt file exists. Copying.."); +- if(!CopyFileToDirectory(tmpDirPath, cloudInitTmpDirPath, "nics.txt")) { ++ if (!CopyFileToDirectory(tmpDirPath, cloudInitTmpDirPath, "nics.txt")) { + goto done; + } + } +@@ -973,7 +973,7 @@ CloudInitSetup(const char *tmpDirPath) + } + + sLog(log_info, "Copying main configuration file cust.cfg"); +- if(!CopyFileToDirectory(tmpDirPath, cloudInitTmpDirPath, "cust.cfg")) { ++ if (!CopyFileToDirectory(tmpDirPath, cloudInitTmpDirPath, "cust.cfg")) { + goto done; + } + +@@ -992,7 +992,7 @@ done: + "/bin/rm -rf %s", + cloudInitTmpDirPath); + command[sizeof(command) - 1] = '\0'; +- ForkExecAndWaitCommand(command); ++ ForkExecAndWaitCommand(command, false); + } + sLog(log_error, "Setting generic error status in vmx. \n"); + SetCustomizationStatusInVmx(TOOLSDEPLOYPKG_RUNNING, +@@ -1016,7 +1016,7 @@ CopyFileToDirectory(const char* srcPath, const char* destPath, + snprintf(command, sizeof(command), "/bin/cp %s/%s %s/%s.tmp", srcPath, + fileName, destPath, fileName); + command[sizeof(command) - 1] = '\0'; +- forkExecResult = ForkExecAndWaitCommand(command); ++ forkExecResult = ForkExecAndWaitCommand(command, false); + if (forkExecResult != 0) { + SetDeployError("Error while copying file %s: %s", fileName, + strerror(errno)); +@@ -1026,7 +1026,7 @@ CopyFileToDirectory(const char* srcPath, const char* destPath, + fileName, destPath, fileName); + command[sizeof(command) - 1] = '\0'; + +- forkExecResult = ForkExecAndWaitCommand(command); ++ forkExecResult = ForkExecAndWaitCommand(command, false); + if (forkExecResult != 0) { + SetDeployError("Error while renaming temp file %s: %s", fileName, + strerror(errno)); +@@ -1090,7 +1090,7 @@ UseCloudInitWorkflow(const char* dirPath) + sLog(log_info, "cust.cfg is found in '%s' directory.", dirPath); + } + +- forkExecResult = ForkExecAndWaitCommand(cloudInitCommand); ++ forkExecResult = ForkExecAndWaitCommand(cloudInitCommand, true); + if (forkExecResult != 0) { + sLog(log_info, "cloud-init is not installed"); + free(cfgFullPath); +@@ -1194,7 +1194,7 @@ Deploy(const char* packageName) + deployPkgStatus = CloudInitSetup(tmpDirPath); + } else { + sLog(log_info, "Executing traditional GOSC workflow"); +- deploymentResult = ForkExecAndWaitCommand(command); ++ deploymentResult = ForkExecAndWaitCommand(command, false); + free(command); + + if (deploymentResult != CUST_SUCCESS) { +@@ -1260,7 +1260,7 @@ Deploy(const char* packageName) + strcat(cleanupCommand, tmpDirPath); + + sLog(log_info, "Launching cleanup. \n"); +- if (ForkExecAndWaitCommand(cleanupCommand) != 0) { ++ if (ForkExecAndWaitCommand(cleanupCommand, false) != 0) { + sLog(log_warning, "Error while clean up tmp directory %s: (%s)", + tmpDirPath, strerror (errno)); + } +@@ -1289,7 +1289,7 @@ Deploy(const char* packageName) + int rebootComandResult = 0; + do { + sLog(log_info, "Rebooting\n"); +- rebootComandResult = ForkExecAndWaitCommand("/sbin/telinit 6"); ++ rebootComandResult = ForkExecAndWaitCommand("/sbin/telinit 6", false); + sleep(1); + } while (rebootComandResult == 0); + sLog(log_error, "telinit returned error %d\n", rebootComandResult); +@@ -1499,12 +1499,13 @@ GetFormattedCommandLine(const char* command) + * Fork off the command and wait for it to finish. Classical Linux/Unix + * fork-and-exec. + * +- * @param [IN] command Command to execute ++ * @param [IN] command Command to execute ++ * @param [IN] ignoreStdErr If we ignore stderr when cmd's return code is 0 + * @return Return code from the process (or -1) + * + **/ + int +-ForkExecAndWaitCommand(const char* command) ++ForkExecAndWaitCommand(const char* command, bool ignoreStdErr) + { + ProcessHandle hp; + int retval; +@@ -1522,14 +1523,30 @@ ForkExecAndWaitCommand(const char* command) + + Process_RunToComplete(hp, 100); + sLog(log_info, "Customization command output: %s\n", Process_GetStdout(hp)); +- +- if(Process_GetExitCode(hp) == 0 && strlen(Process_GetStderr(hp)) > 0) { +- // Assume command failed if it wrote to stderr, even if exitCode is 0 +- sLog(log_error, "Customization command failed: %s\n", Process_GetStderr(hp)); +- retval = -1; ++ retval = Process_GetExitCode(hp); ++ ++ if (retval == 0) { ++ if (strlen(Process_GetStderr(hp)) > 0) { ++ if (!ignoreStdErr) { ++ // Assume command failed if it wrote to stderr, even if exitCode is 0 ++ sLog(log_error, ++ "Customization command failed with stderr: %s\n", ++ Process_GetStderr(hp)); ++ retval = -1; ++ } else { ++ // If we choose to ignore stderr, we do not return -1 when return ++ // code is 0. e.g, PR2148977, "cloud-init -v" will return 0 ++ // even there is output in stderr ++ sLog(log_info, "Ignoring stderr output: %s\n", Process_GetStderr(hp)); ++ } ++ } + } else { +- retval = Process_GetExitCode(hp); ++ sLog(log_error, ++ "Customization command failed with exitcode: %d, stderr: %s\n", ++ retval, ++ Process_GetStderr(hp)); + } ++ + Process_Destroy(hp); + return retval; + } +diff --git a/open-vm-tools/libDeployPkg/linuxDeploymentUtilities.c b/open-vm-tools/libDeployPkg/linuxDeploymentUtilities.c +index 83f942da..93e1b0aa 100644 +--- a/open-vm-tools/libDeployPkg/linuxDeploymentUtilities.c ++++ b/open-vm-tools/libDeployPkg/linuxDeploymentUtilities.c +@@ -1,5 +1,5 @@ + /********************************************************* +- * Copyright (C) 2016-2017 VMware, Inc. All rights reserved. ++ * Copyright (C) 2016-2018 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 +@@ -24,7 +24,6 @@ + #include + #include "linuxDeploymentUtilities.h" + +-extern int ForkExecAndWaitCommand(const char* command); + extern LogFunction sLog; + + /** diff --git a/handle-linux-kernel-stat-overflow.patch b/handle-linux-kernel-stat-overflow.patch new file mode 100644 index 0000000..7af6d4d --- /dev/null +++ b/handle-linux-kernel-stat-overflow.patch @@ -0,0 +1,35 @@ +commit c7a186e204cdff46b5e02bcb5208ef8979eaf261 +Author: Oliver Kurth +Date: Mon Sep 17 16:41:18 2018 -0700 + + Handle Linux kernel /proc FS uint32 type stat overflow when calculating + tools rate stats. + + On both 32-bit and 64-bit Linux, tools always parses Linux kernel /proc + FS stats as uint64 values. For rate stats, current - previous can handle + uint64 type stat overflow, but not uint32 type. + +diff --git a/open-vm-tools/services/plugins/guestInfo/perfMonLinux.c b/open-vm-tools/services/plugins/guestInfo/perfMonLinux.c +index fa2344b0..eb74faa5 100644 +--- a/open-vm-tools/services/plugins/guestInfo/perfMonLinux.c ++++ b/open-vm-tools/services/plugins/guestInfo/perfMonLinux.c +@@ -1094,7 +1094,18 @@ GuestInfoAppendRate(Bool emitNameSpace, // IN: + if (reportID == GuestStatID_Linux_DiskRequestQueueAvg) { + valueDelta = ((double)(currentStat->value)) / 10; + } else { +- valueDelta = currentStat->value - previousStat->value; ++ /* ++ * The /proc FS stat can be uint32 type in the kernel on both x86 ++ * and x64 Linux, it is parsed and stored as uint64 in tools, so we ++ * also need to handle uint32 overflow here. ++ */ ++ if (currentStat->value < previousStat->value && ++ previousStat->value <= MAX_UINT32) { ++ valueDelta = (uint32)(currentStat->value) - ++ (uint32)(previousStat->value); ++ } else { ++ valueDelta = currentStat->value - previousStat->value; ++ } + } + + valueDouble = valueDelta / timeDelta; diff --git a/open-vm-tools.changes b/open-vm-tools.changes index 8db08e4..399a7a7 100644 --- a/open-vm-tools.changes +++ b/open-vm-tools.changes @@ -1,3 +1,32 @@ +------------------------------------------------------------------- +Fri Oct 12 20:43:54 UTC 2018 - kallan@suse.com + +- Added Handle Linux kernel /proc FS uint32 type stat overflow when calculating + (bsc#1110793). + + handle-linux-kernel-stat-overflow.patch + On both 32-bit and 64-bit Linux, tools always parses Linux kernel /proc + FS stats as uint64 values. For rate stats, current - previous can handle + uint64 type stat overflow, but not uint32 type. +- Added patch for Optional override for short and long OS names sent from Tools + (bsc#1047469). + + optional-override-os-name.patch + Added support for customers to override the returned long and short OS + names through the tools config file. If the setting is present, then names + gathered by hostinfo will be ignored. The user is responsible for setting + the appropriate names. +- Added patch for Workaround for false negative result when detecting + cloud-init existance (bsc#1111619) + + false-negative-cloud-init.patch + "cloud-init -v" cmd is used to detect if cloud-init is properly configured + and it works on most linux distros. However in some linux distro like + Amazon Linux 2, "cloud-init -v" will print result to stderr instead of + stdout and it makes "forkExecAndWaitCommand" give false negative result. + 1. added a new bool switch in "ForkExecAndWaitCommand" to choose + if we should ignore the stderr output when the return code is 0 + 2. removed unnecessary reference for "ForkExecAndWaitCommand" in + linuxDeploymentUtilities.c + 3. trivial change for some formatting + ------------------------------------------------------------------- Wed Aug 15 18:07:49 UTC 2018 - kallan@suse.com @@ -43,7 +72,7 @@ Tue May 17 20:14:03 UTC 2018 - mlatimer@suse.com ------------------------------------------------------------------- Fri Apr 6 19:25:22 UTC 2018 - mlatimer@suse.com -- Update to 10.2.5 (build 8068406) +- Update to 10.2.5 (build 8068406) (boo#1089181) + Compatible with supported versions of VMware vSphere ESXi 5.5 and later, VMware Workstation 14.0 and VMware Fusion 10.0.0. + Quiesced snapshot: Ability to exclude specific file systems from diff --git a/open-vm-tools.spec b/open-vm-tools.spec index 5f155d3..6d5fdcf 100644 --- a/open-vm-tools.spec +++ b/open-vm-tools.spec @@ -146,6 +146,9 @@ Obsoletes: open-vm-tools-deploypkg <= 10.0.5 Supplements: modalias(pci:v000015ADd*sv*sd*bc*sc*i*) ExclusiveArch: %ix86 x86_64 #Upstream patches +Patch0: optional-override-os-name.patch +Patch1: handle-linux-kernel-stat-overflow.patch +Patch2: false-negative-cloud-init.patch %systemd_requires @@ -211,6 +214,9 @@ if you intend to create own plugins for vmtoolsd. %setup -q -n %{tarname}-%{version}-%{bldnum} # fix for an rpmlint warning regarding wrong line feeds sed -i -e "s/\r//" README +%patch0 -p2 +%patch1 -p2 +%patch2 -p2 %build %if %{with_X} diff --git a/optional-override-os-name.patch b/optional-override-os-name.patch new file mode 100644 index 0000000..a031dee --- /dev/null +++ b/optional-override-os-name.patch @@ -0,0 +1,156 @@ +commit 87593b29e5c337141be65e4430fb95a4f1741afb +Author: Oliver Kurth +Date: Fri Oct 5 13:55:27 2018 -0700 + + Optional override for short and long OS names sent from Tools + + Added support for customers to override the returned long and short OS + names through the tools config file. If the setting is present, then names + gathered by hostinfo will be ignored. The user is responsible for setting + the appropriate names. + + The override will be ignored if the short-name setting is not present in + tools.conf. + + An empty string will be sent for the long OS name if only the short-name + setting is present. + + Appropriate warning msg will be generated in both cases. + + Example of the conf setting: + + [guestosinfo] + short-name = centos6-64 + long-name = some long name + +diff --git a/open-vm-tools/lib/include/conf.h b/open-vm-tools/lib/include/conf.h +index af685348..f9698c18 100644 +--- a/open-vm-tools/lib/include/conf.h ++++ b/open-vm-tools/lib/include/conf.h +@@ -169,6 +169,32 @@ + */ + + ++/* ++ ****************************************************************************** ++ * BEGIN GuestOSInfo goodies. ++ */ ++ ++/** ++ * Defines the string used for the GuestOSInfo config file group. ++ */ ++#define CONFGROUPNAME_GUESTOSINFO "guestosinfo" ++ ++/** ++ * Lets users override the short OS name sent by Tools. ++ */ ++#define CONFNAME_GUESTOSINFO_SHORTNAME "short-name" ++ ++/** ++ * Lets users override the long OS name sent by Tools. ++ */ ++#define CONFNAME_GUESTOSINFO_LONGNAME "long-name" ++ ++/* ++ * END GuestOSInfo goodies. ++ ****************************************************************************** ++ */ ++ ++ + /* + ****************************************************************************** + * BEGIN Unity goodies. +diff --git a/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c b/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c +index 2cdad508..f31eddf0 100644 +--- a/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c ++++ b/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c +@@ -483,6 +483,8 @@ GuestInfoGather(gpointer data) + Bool lowPriorityChanged; + int maxIPv4RoutesToGather; + int maxIPv6RoutesToGather; ++ gchar *osNameOverride; ++ gchar *osNameFullOverride; + + g_debug("Entered guest info gather.\n"); + +@@ -498,26 +500,67 @@ GuestInfoGather(gpointer data) + g_warning("Failed to update VMDB with tools version.\n"); + } + +- /* Gather all the relevant guest information. */ +- osString = Hostinfo_GetOSName(); +- if (osString == NULL) { +- g_warning("Failed to get OS info.\n"); ++ /* Check for manual override of guest information in the config file */ ++ osNameOverride = VMTools_ConfigGetString(ctx->config, ++ CONFGROUPNAME_GUESTOSINFO, ++ CONFNAME_GUESTOSINFO_SHORTNAME, ++ NULL); ++ osNameFullOverride = VMTools_ConfigGetString(ctx->config, ++ CONFGROUPNAME_GUESTOSINFO, ++ CONFNAME_GUESTOSINFO_LONGNAME, ++ NULL); ++ /* If only the OS Full Name is provided, continue as normal, but emit ++ * warning. */ ++ if (osNameOverride == NULL && osNameFullOverride != NULL) { ++ g_warning("Ignoring " CONFNAME_GUESTOSINFO_LONGNAME " override.\n"); ++ g_warning("To use the GOS name override, " ++ CONFNAME_GUESTOSINFO_SHORTNAME " must be present in the " ++ "tools.conf file.\n"); ++ g_free(osNameFullOverride); ++ } ++ ++ /* Only use override if at least the short OS name is provided */ ++ if (osNameOverride == NULL) { ++ /* Gather all the relevant guest information. */ ++ osString = Hostinfo_GetOSName(); ++ if (osString == NULL) { ++ g_warning("Failed to get OS info.\n"); ++ } else { ++ if (!GuestInfoUpdateVmdb(ctx, INFO_OS_NAME_FULL, osString, 0)) { ++ g_warning("Failed to update VMDB\n"); ++ } ++ } ++ free(osString); ++ ++ osString = Hostinfo_GetOSGuestString(); ++ if (osString == NULL) { ++ g_warning("Failed to get OS info.\n"); ++ } else { ++ if (!GuestInfoUpdateVmdb(ctx, INFO_OS_NAME, osString, 0)) { ++ g_warning("Failed to update VMDB\n"); ++ } ++ } ++ free(osString); + } else { +- if (!GuestInfoUpdateVmdb(ctx, INFO_OS_NAME_FULL, osString, 0)) { ++ /* Use osName and osNameFull provided in config file */ ++ if (osNameFullOverride == NULL) { ++ g_warning(CONFNAME_GUESTOSINFO_LONGNAME " was not set in " ++ "tools.conf, using empty string.\n"); ++ } ++ if (!GuestInfoUpdateVmdb(ctx, ++ INFO_OS_NAME_FULL, ++ (osNameFullOverride == NULL) ? "" : osNameFullOverride, ++ 0)) { + g_warning("Failed to update VMDB\n"); + } +- } +- free(osString); ++ g_free(osNameFullOverride); + +- osString = Hostinfo_GetOSGuestString(); +- if (osString == NULL) { +- g_warning("Failed to get OS info.\n"); +- } else { +- if (!GuestInfoUpdateVmdb(ctx, INFO_OS_NAME, osString, 0)) { ++ if (!GuestInfoUpdateVmdb(ctx, INFO_OS_NAME, osNameOverride, 0)) { + g_warning("Failed to update VMDB\n"); + } ++ g_free(osNameOverride); ++ g_debug("Using values in tools.conf to override OS Name.\n"); + } +- free(osString); + + #if !defined(USERWORLD) + disableQueryDiskInfo =