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 =