From: Oliver Kurth Date: Fri, 15 Sep 2017 18:23:40 +0000 (-0700) Subject: Generate backup manifest files for quiesced snapshots on Linux. X-Git-Tag: stable-10.2.0~208 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9f3c5f179ed252f31c15e71ca45c83ae33a4dc62;p=thirdparty%2Fopen-vm-tools.git Generate backup manifest files for quiesced snapshots on Linux. After a successful quiesced snapshot of a Linux guest, the snapshot is reported as not quiesced. The underlying cause is: - a snapshot is identified as quiesced if and only if a backup manifest file was provided for the snapshot; and - backup manifest files are not provided for quiesced snapshots on Linux. To fix the problem, VMTools will generate backup manifest files for quiesced snaphots taken on Linux, and VMX will accept and store such files. This change is for the VMTools side of the change. The VMX change defines a new VMBACKUP_EVENT value relied on by the VMTools change. Changes in this commit include: - new source files syncManifest.h and syncManifest.c with code to generate the manifest file, and updates to syncDriverOps.c to invoke that code. - a new "SyncDriver_GetAttr" interface in the syncDriver code, used by the SyncManifest code to obtain the name of the backend provider and whether or not it is capable of quiescing. - makefile and configure boiler plate to add the two new source files to open-vm-tools and tools-for-linux. - a new tools.conf setting enableXmlManifest that specifies whether VMTools generates backup manifests for Linux. For now, the default value of this setting will be false. --- diff --git a/open-vm-tools/lib/include/syncDriver.h b/open-vm-tools/lib/include/syncDriver.h index 92452a236..4cb71b491 100644 --- a/open-vm-tools/lib/include/syncDriver.h +++ b/open-vm-tools/lib/include/syncDriver.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2005-2016 VMware, Inc. All rights reserved. + * Copyright (C) 2005-2017 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 @@ -27,7 +27,7 @@ #include "vm_basic_types.h" -#ifdef _WIN32 /* { */ +#if defined(_WIN32) /* { */ # include # define SYNCDRIVER_INVALID_HANDLE INVALID_HANDLE_VALUE @@ -55,6 +55,10 @@ Bool SyncDriver_Thaw(const SyncDriverHandle handle); SyncDriverStatus SyncDriver_QueryStatus(const SyncDriverHandle handle, int32 timeout); void SyncDriver_CloseHandle(SyncDriverHandle *handle); +#if defined(__linux__) +void SyncDriver_GetAttr(const SyncDriverHandle handle, const char **name, + Bool *quiesces); +#endif #endif diff --git a/open-vm-tools/lib/syncDriver/syncDriverInt.h b/open-vm-tools/lib/syncDriver/syncDriverInt.h index 8878b3c70..04f37bf23 100644 --- a/open-vm-tools/lib/syncDriver/syncDriverInt.h +++ b/open-vm-tools/lib/syncDriver/syncDriverInt.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2011-2016 VMware, Inc. All rights reserved. + * Copyright (C) 2011-2017 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 @@ -46,6 +46,10 @@ typedef SyncDriverErr (*SyncFreezeFn)(const GSList *paths, typedef struct SyncHandle { SyncDriverErr (*thaw)(const SyncDriverHandle handle); void (*close)(SyncDriverHandle handle); +#if defined(__linux__) + void (*getattr)(const SyncDriverHandle handle, const char **name, + Bool *quiesces); +#endif } SyncHandle; #if defined(__linux__) diff --git a/open-vm-tools/lib/syncDriver/syncDriverLinux.c b/open-vm-tools/lib/syncDriver/syncDriverLinux.c index da0a8cb6e..db042da4f 100644 --- a/open-vm-tools/lib/syncDriver/syncDriverLinux.c +++ b/open-vm-tools/lib/syncDriver/syncDriverLinux.c @@ -116,6 +116,29 @@ LinuxFiClose(SyncDriverHandle handle) } +/* + ******************************************************************************* + * LinuxFiGetAttr -- */ /** + * + * Return some attributes of the backend provider + * + * @param[out] name name of backend provider + * @param[out] quiesces TRUE (FALSE) if provider is (is not) capable + * of quiescing. + * + ******************************************************************************* + */ + +static void +LinuxFiGetAttr(const SyncDriverHandle handle, // IN (ignored) + const char **name, // OUT + Bool *quiesces) // OUT +{ + *name = "fifreeze"; + *quiesces = TRUE; +} + + /* ******************************************************************************* * LinuxDriver_Freeze -- */ /** @@ -159,6 +182,7 @@ LinuxDriver_Freeze(const GSList *paths, sync->driver.thaw = LinuxFiThaw; sync->driver.close = LinuxFiClose; + sync->driver.getattr = LinuxFiGetAttr; /* * Ensure we did not get an empty list diff --git a/open-vm-tools/lib/syncDriver/syncDriverPosix.c b/open-vm-tools/lib/syncDriver/syncDriverPosix.c index f499faa47..51979b298 100644 --- a/open-vm-tools/lib/syncDriver/syncDriverPosix.c +++ b/open-vm-tools/lib/syncDriver/syncDriverPosix.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2005-2016 VMware, Inc. All rights reserved. + * Copyright (C) 2005-2017 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 @@ -379,3 +379,40 @@ SyncDriver_CloseHandle(SyncDriverHandle *handle) // IN/OUT } } + +#if defined(__linux__) +/* + *----------------------------------------------------------------------------- + * + * SyncDriver_GetAttr -- + * + * Returns attributes of the backend provider for this handle. + * If the backend does not supply a getattr function, it's treated + * as non-quiescing. + * + * Results: + * No return value. + * Sets OUT parameters: + * *name: pointer to backend provider name + * *quiesces: indicates whether backend is capable of quiescing. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +void +SyncDriver_GetAttr(const SyncDriverHandle handle, // IN + const char **name, // OUT + Bool *quiesces) // OUT +{ + + if (handle != SYNCDRIVER_INVALID_HANDLE && handle->getattr != NULL) { + handle->getattr(handle, name, quiesces); + } else { + *name = NULL; + *quiesces = FALSE; + } +} +#endif /* __linux__ */ diff --git a/open-vm-tools/services/plugins/vmbackup/Makefile.am b/open-vm-tools/services/plugins/vmbackup/Makefile.am index 81fc5c7f2..ed561a7af 100644 --- a/open-vm-tools/services/plugins/vmbackup/Makefile.am +++ b/open-vm-tools/services/plugins/vmbackup/Makefile.am @@ -1,5 +1,5 @@ ################################################################################ -### Copyright (C) 2009-2016 VMware, Inc. All rights reserved. +### Copyright (C) 2009-2017 VMware, Inc. All rights reserved. ### ### This program is free software; you can redistribute it and/or modify ### it under the terms of version 2 of the GNU General Public License as @@ -33,6 +33,7 @@ libvmbackup_la_SOURCES += nullProvider.c libvmbackup_la_SOURCES += scriptOps.c libvmbackup_la_SOURCES += stateMachine.c libvmbackup_la_SOURCES += syncDriverOps.c +libvmbackup_la_SOURCES += syncManifest.c libvmbackup_la_SOURCES += vmBackupSignals.c BUILT_SOURCES = diff --git a/open-vm-tools/services/plugins/vmbackup/syncDriverOps.c b/open-vm-tools/services/plugins/vmbackup/syncDriverOps.c index e587f7fcf..682686df0 100644 --- a/open-vm-tools/services/plugins/vmbackup/syncDriverOps.c +++ b/open-vm-tools/services/plugins/vmbackup/syncDriverOps.c @@ -28,6 +28,7 @@ #include "procMgr.h" #include "syncDriver.h" #include "util.h" +#include "syncManifest.h" #ifdef _WIN32 #include @@ -40,6 +41,7 @@ typedef struct VmBackupDriverOp { Bool freeze; Bool canceled; SyncDriverHandle *syncHandle; + SyncManifest *manifest; } VmBackupDriverOp; @@ -122,6 +124,9 @@ VmBackupDriverOpQuery(VmBackupOp *_op) // IN break; } } else { + if (op->manifest != NULL) { + SyncManifestSend(op->manifest); + } ret = VMBACKUP_STATUS_FINISHED; } @@ -149,7 +154,9 @@ static void VmBackupDriverOpRelease(VmBackupOp *_op) // IN { VmBackupDriverOp *op = (VmBackupDriverOp *) _op; + g_free(op->syncHandle); + SyncManifestRelease(op->manifest); free(op); } @@ -231,11 +238,13 @@ VmBackupNewDriverOp(VmBackupState *state, // IN state->enableNullDriver : FALSE, op->syncHandle); } else { + op->manifest = SyncNewManifest(state, *op->syncHandle); success = VmBackupDriverThaw(op->syncHandle); } if (!success) { g_warning("Error %s filesystems.", freeze ? "freezing" : "thawing"); g_free(op->syncHandle); + SyncManifestRelease(op->manifest); free(op); op = NULL; } diff --git a/open-vm-tools/services/plugins/vmbackup/syncManifest.c b/open-vm-tools/services/plugins/vmbackup/syncManifest.c new file mode 100644 index 000000000..7166ccc26 --- /dev/null +++ b/open-vm-tools/services/plugins/vmbackup/syncManifest.c @@ -0,0 +1,175 @@ +/********************************************************* + * Copyright (C) 2017 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. + * + *********************************************************/ + +/* + * syncManifest.c -- + * + * Implements a simple xml-based backup manifest file for quiesced snapshots + * on Linux. + */ + +#include "vmBackupInt.h" +#include "syncDriver.h" +#include "syncManifest.h" +#include "vm_tools_version.h" + +#include +#include +#include +#include + +/* + * Name and format of the manifest file. + */ +static const char syncManifestName[] = "quiesce_manifest.xml"; +static const char syncManifestFmt[] = { + "\n" + " %d\n" /* version of tools */ + " %s\n" /* name of backend provider */ + "\n" +}; + +/* + * tools.conf switch to enable manifest generation + */ +static const char syncManifestSwitch[] = "enableXmlManifest"; + + +/* + *----------------------------------------------------------------------------- + * + * SyncNewManifest -- + * + * Create a new SyncManifest structure. + * + * Results: + * Pointer to structure on success, otherwise NULL. + * + *----------------------------------------------------------------------------- + */ + +SyncManifest * +SyncNewManifest(VmBackupState *state, // IN + SyncDriverHandle handle) // IN +{ + Bool providerQuiesces; + const char *providerName; + SyncManifest *manifest; + + /* + * XXX - feature is to be disabled by default until approved by QE. + */ + if (!VMTools_ConfigGetBoolean(state->ctx->config, "vmbackup", + syncManifestSwitch, FALSE)) { + g_debug("No backup manifest - %s is false\n", + syncManifestSwitch); + return NULL; + } + + if (!state->generateManifests) { + g_debug("No backup manifest requested\n"); + return NULL; + } + + SyncDriver_GetAttr(handle, &providerName, &providerQuiesces); + if (!providerQuiesces) { + g_debug("No backup manifest needed since using " + "non-quiescing backend.\n"); + return NULL; + } + + manifest = g_new0(SyncManifest, 1); + manifest->path = g_strdup_printf("%s/%s", state->configDir, + syncManifestName); + manifest->providerName = g_strdup(providerName); + return manifest; +} + + +/* + *----------------------------------------------------------------------------- + * + * SyncManifestRelease -- + * + * Free a manifest structure. + * + * Results: + * None + * + *----------------------------------------------------------------------------- + */ + +void +SyncManifestRelease(SyncManifest *manifest) // IN +{ + if (manifest != NULL) { + g_free(manifest->path); + g_free(manifest->providerName); + g_free(manifest); + } +} + + +/* + *----------------------------------------------------------------------------- + * + * SyncManifestSend -- + * + * Generate manifest file and send it to vmx. + * + * Results: + * TRUE on success, FALSE on failure. + * + * Side effects: + * On success, writes out the backup manifest file for a quiesced + * snapshot and sends the file's path to vmx. + * + *----------------------------------------------------------------------------- + */ + +Bool +SyncManifestSend(SyncManifest *manifest) // IN +{ + FILE *f; + int ret; + + unlink(manifest->path); + f = fopen(manifest->path, "w"); + if (f == NULL) { + g_warning("Error opening backup manifest file %s\n", + manifest->path); + return FALSE; + } + + ret = fprintf(f, syncManifestFmt, TOOLS_VERSION_CURRENT, + manifest->providerName); + fclose(f); + if (ret < 0) { + g_warning("Error writing backup manifest file %s: %d %s\n", + manifest->path, errno, strerror(errno)); + return FALSE; + } + + if (!VmBackup_SendEvent(VMBACKUP_EVENT_GENERIC_MANIFEST, + VMBACKUP_SUCCESS, manifest->path)) { + g_warning("Error trying to send VMBACKUP_EVENT_GENERIC_MANIFEST.\n"); + return FALSE; + } + + return TRUE; +} diff --git a/open-vm-tools/services/plugins/vmbackup/syncManifest.h b/open-vm-tools/services/plugins/vmbackup/syncManifest.h new file mode 100644 index 000000000..76966ccac --- /dev/null +++ b/open-vm-tools/services/plugins/vmbackup/syncManifest.h @@ -0,0 +1,58 @@ +/********************************************************* + * Copyright (C) 2017 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 syncManifest.h + * + * Interface definitions for sync driver manifest file generation. + * On Linux, generate an xml-format manifest file when quiescing + * is done via the sync driver backend that uses "FIFREEZE" and + * "FITHAW" ioctls. On other OSes, or on Linux with other sync + * driver backends, no manifest is generated for the sync driver. + */ + +#ifndef _SYNCMANIFEST_H_ +#define _SYNCMANIFEST_H_ + +#if defined(__linux__) + +typedef struct { + char *path; + char *providerName; +} SyncManifest; + +SyncManifest * +SyncNewManifest(VmBackupState *state, SyncDriverHandle handle); + +Bool +SyncManifestSend(SyncManifest *manifest); + +void +SyncManifestRelease(SyncManifest *manifest); + +#else /* !defined(__linux__) */ + +typedef void SyncManifest; + +#define SyncNewManifest(s, h) (NULL) +#define SyncManifestSend(m) (TRUE) +#define SyncManifestRelease(m) ASSERT(m == NULL) + +#endif /* defined(__linux__) */ + +#endif /* _SYNCMANIFEST_H_*/