From: James Harper Date: Fri, 2 Apr 2010 10:51:03 +0000 (+0200) Subject: Apply James' plugin patch X-Git-Tag: Release-5.2.1~1550 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=822bfbfb16cec0d6aa526a5211fac199d8e943ec;p=bacula%2Fbacula Apply James' plugin patch --- diff --git a/bacula/src/filed/fd_plugins.h b/bacula/src/filed/fd_plugins.h index 0facb47f08..94ebe828b6 100644 --- a/bacula/src/filed/fd_plugins.h +++ b/bacula/src/filed/fd_plugins.h @@ -169,7 +169,8 @@ typedef enum { bEventLevel = 11, bEventSince = 12, bEventCancelCommand = 13, - bEventInitializeVSS = 14 + bEventInitializeVSS = 14, + bEventPrepareVSS = 15, } bEventType; typedef struct s_bEvent { diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index bcdc459a36..82f6801cde 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -1788,6 +1788,24 @@ static int verify_cmd(JCR *jcr) return 0; /* return and terminate command loop */ } +#ifdef WIN32_VSS +static bool vss_restore_init_callback(JCR *jcr, int init_type) +{ + switch (init_type) + { + case VSS_INIT_RESTORE_AFTER_INIT: + generate_plugin_event(jcr, bEventInitializeVSS); + return true; + case VSS_INIT_RESTORE_AFTER_GATHER: + generate_plugin_event(jcr, bEventPrepareVSS); + return true; + default: + return false; + break; + } +} +#endif + /** * Do a Restore for Director * @@ -1805,6 +1823,21 @@ static int restore_cmd(JCR *jcr) * Scan WHERE (base directory for restore) from command */ Dmsg0(150, "restore command\n"); +#if defined(WIN32_VSS) + + /* TODO: this should be given from the director */ + enable_vss = 1; + + Dmsg2(50, "g_pVSSClient = %p, enable_vss = %d\n", g_pVSSClient, enable_vss); + // capture state here, if client is backed up by multiple directors + // and one enables vss and the other does not then enable_vss can change + // between here and where its evaluated after the job completes. + jcr->VSS = g_pVSSClient && enable_vss; + if (jcr->VSS) { + /* Run only one at a time */ + P(vss_mutex); + } +#endif /* Pickup where string */ args = get_memory(dir->msglen+1); *args = 0; @@ -1863,6 +1896,32 @@ static int restore_cmd(JCR *jcr) start_dir_heartbeat(jcr); generate_daemon_event(jcr, "JobStart"); generate_plugin_event(jcr, bEventStartRestoreJob); + +#if defined(WIN32_VSS) + /* START VSS ON WIN32 */ + if (jcr->VSS) { + if (g_pVSSClient->InitializeForRestore(jcr, vss_restore_init_callback)) { + /* inform user about writer states */ + int i; + for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) { + int msg_type = M_INFO; + if (g_pVSSClient->GetWriterState(i) < 1) { + msg_type = M_WARNING; + jcr->JobErrors++; + } + if (g_pVSSClient->GetWriterState(i) < 1) { + Jmsg(jcr, M_WARNING, 0, _("VSS Writer (PreRestore): %s\n"), g_pVSSClient->GetWriterInfo(i)); + jcr->JobErrors++; + } + } + } else { + berrno be; + Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror()); + } + run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS"); + } +#endif + do_restore(jcr); stop_dir_heartbeat(jcr); @@ -1882,6 +1941,30 @@ static int restore_cmd(JCR *jcr) /* Inform Storage daemon that we are done */ sd->signal(BNET_TERMINATE); +#if defined(WIN32_VSS) + /* STOP VSS ON WIN32 */ + /* tell vss to close the restore session */ + Dmsg0(0, "About to call CloseRestore\n"); + if (jcr->VSS) { + Dmsg0(0, "Really about to call CloseRestore\n"); + if (g_pVSSClient->CloseRestore()) { + Dmsg0(0, "CloseRestore success\n"); + /* inform user about writer states */ + for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) { + int msg_type = M_INFO; + if (g_pVSSClient->GetWriterState(i) < 1) { + msg_type = M_WARNING; + jcr->JobErrors++; + } + Jmsg(jcr, msg_type, 0, _("VSS Writer (RestoreComplete): %s\n"), g_pVSSClient->GetWriterInfo(i)); + } + } + else + Dmsg1(0, "CloseRestore fail - %08x\n", errno); + V(vss_mutex); + } +#endif + bail_out: bfree_and_null(jcr->where); diff --git a/bacula/src/win32/filed/vss.cpp b/bacula/src/win32/filed/vss.cpp index 45ce160c69..334f24bbc8 100644 --- a/bacula/src/win32/filed/vss.cpp +++ b/bacula/src/win32/filed/vss.cpp @@ -136,7 +136,11 @@ bool VSSClient::InitializeForBackup(JCR *jcr) } - +bool VSSClient::InitializeForRestore(JCR *jcr, bool (*VssInitCallback)(JCR *, int)) +{ + m_jcr = jcr; + return Initialize(0, TRUE, VssInitCallback); +} bool VSSClient::GetShadowPath(const char *szFilePath, char *szShadowPath, int nBuflen) { diff --git a/bacula/src/win32/filed/vss.h b/bacula/src/win32/filed/vss.h index 5b2b355a96..45fdfbd125 100644 --- a/bacula/src/win32/filed/vss.h +++ b/bacula/src/win32/filed/vss.h @@ -46,6 +46,9 @@ #ifdef WIN32_VSS +#define VSS_INIT_RESTORE_AFTER_INIT 1 +#define VSS_INIT_RESTORE_AFTER_GATHER 2 + // some forward declarations struct IVssAsync; @@ -57,8 +60,12 @@ public: // Backup Process bool InitializeForBackup(JCR *jcr); + bool InitializeForRestore(JCR *jcr, bool (*VssInitCallback)(JCR *, int) = NULL); + //bool GatherForRestore() = 0; + //bool PrepareForRestore() = 0; virtual bool CreateSnapshots(char* szDriveLetters) = 0; virtual bool CloseBackup() = 0; + virtual bool CloseRestore() = 0; virtual const char* GetDriverName() = 0; bool GetShadowPath (const char* szFilePath, char* szShadowPath, int nBuflen); bool GetShadowPathW (const wchar_t* szFilePath, wchar_t* szShadowPath, int nBuflen); /* nBuflen in characters */ @@ -73,7 +80,7 @@ public: IUnknown *GetVssObject() { return m_pVssObject; }; private: - virtual bool Initialize(DWORD dwContext, bool bDuringRestore = FALSE) = 0; + virtual bool Initialize(DWORD dwContext, bool bDuringRestore = FALSE, bool (*VssInitCallback)(JCR *, int) = NULL) = 0; virtual bool WaitAndCheckForAsyncOperation(IVssAsync* pAsync) = 0; virtual void QuerySnapshotSet(GUID snapshotSetID) = 0; @@ -106,9 +113,10 @@ public: virtual ~VSSClientXP(); virtual bool CreateSnapshots(char* szDriveLetters); virtual bool CloseBackup(); + virtual bool CloseRestore(); virtual const char* GetDriverName() { return "VSS WinXP"; }; private: - virtual bool Initialize(DWORD dwContext, bool bDuringRestore); + virtual bool Initialize(DWORD dwContext, bool bDuringRestore, bool (*VssInitCallback)(JCR *, int) = NULL); virtual bool WaitAndCheckForAsyncOperation(IVssAsync* pAsync); virtual void QuerySnapshotSet(GUID snapshotSetID); bool CheckWriterStatus(); @@ -121,9 +129,10 @@ public: virtual ~VSSClient2003(); virtual bool CreateSnapshots(char* szDriveLetters); virtual bool CloseBackup(); + virtual bool CloseRestore(); virtual const char* GetDriverName() { return "VSS Win 2003"; }; private: - virtual bool Initialize(DWORD dwContext, bool bDuringRestore); + virtual bool Initialize(DWORD dwContext, bool bDuringRestore, bool (*VssInitCallback)(JCR *, int) = NULL); virtual bool WaitAndCheckForAsyncOperation(IVssAsync* pAsync); virtual void QuerySnapshotSet(GUID snapshotSetID); bool CheckWriterStatus(); @@ -136,9 +145,10 @@ public: virtual ~VSSClientVista(); virtual bool CreateSnapshots(char* szDriveLetters); virtual bool CloseBackup(); + virtual bool CloseRestore(); virtual const char* GetDriverName() { return "VSS Vista"; }; private: - virtual bool Initialize(DWORD dwContext, bool bDuringRestore); + virtual bool Initialize(DWORD dwContext, bool bDuringRestore, bool (*VssInitCallback)(JCR *, int) = NULL); virtual bool WaitAndCheckForAsyncOperation(IVssAsync* pAsync); virtual void QuerySnapshotSet(GUID snapshotSetID); bool CheckWriterStatus(); diff --git a/bacula/src/win32/filed/vss_generic.cpp b/bacula/src/win32/filed/vss_generic.cpp index 4719994547..3ab65eec55 100644 --- a/bacula/src/win32/filed/vss_generic.cpp +++ b/bacula/src/win32/filed/vss_generic.cpp @@ -230,8 +230,10 @@ VSSClientGeneric::~VSSClientGeneric() } // Initialize the COM infrastructure and the internal pointers -bool VSSClientGeneric::Initialize(DWORD dwContext, bool bDuringRestore) +bool VSSClientGeneric::Initialize(DWORD dwContext, bool bDuringRestore, bool (*VssInitCallback)(JCR *, int)) { + CComPtr pAsync1; + if (!(p_CreateVssBackupComponents && p_VssFreeSnapshotProperties)) { Dmsg2(0, "VSSClientGeneric::Initialize: p_CreateVssBackupComponents = 0x%08X, p_VssFreeSnapshotProperties = 0x%08X\n", p_CreateVssBackupComponents, p_VssFreeSnapshotProperties); errno = ENOSYS; @@ -317,7 +319,6 @@ bool VSSClientGeneric::Initialize(DWORD dwContext, bool bDuringRestore) return false; } - CComPtr pAsync1; // 3. GatherWriterMetaData hr = ((IVssBackupComponents*) m_pVssObject)->GatherWriterMetadata(&pAsync1.p); if (FAILED(hr)) { @@ -328,6 +329,57 @@ bool VSSClientGeneric::Initialize(DWORD dwContext, bool bDuringRestore) // Waits for the async operation to finish and checks the result WaitAndCheckForAsyncOperation(pAsync1.p); } + else + { + WCHAR *xml; + HRESULT hr; + int fd; + struct stat stat; + + /* obviously this is just temporary - the xml should come from somewhere like the catalog */ + fd = open("C:\\james.xml", O_RDONLY); + Dmsg1(0, "fd = %d\n", fd); + fstat(fd, &stat); + Dmsg1(0, "size = %d\n", stat.st_size); + xml = new WCHAR[stat.st_size / sizeof(WCHAR) + 1]; + read(fd, xml, stat.st_size); + close(fd); + xml[stat.st_size / sizeof(WCHAR)] = 0; + + // 1. InitializeForRestore + hr = ((IVssBackupComponents*) m_pVssObject)->InitializeForRestore(xml); + if (FAILED(hr)) { + Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->InitializeForRestore returned 0x%08X\n", hr); + errno = b_errno_win32; + return false; + } + VssInitCallback(m_jcr, VSS_INIT_RESTORE_AFTER_INIT); + + // 2. GatherWriterMetaData + hr = ((IVssBackupComponents*) m_pVssObject)->GatherWriterMetadata(&pAsync1.p); + if (FAILED(hr)) { + Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->GatherWriterMetadata returned 0x%08X\n", hr); + errno = b_errno_win32; + return false; + } + WaitAndCheckForAsyncOperation(pAsync1.p); + VssInitCallback(m_jcr, VSS_INIT_RESTORE_AFTER_GATHER); + + // 3. PreRestore + hr = ((IVssBackupComponents*) m_pVssObject)->PreRestore(&pAsync1.p); + if (FAILED(hr)) { + Dmsg1(0, "VSSClientGeneric::Initialize: IVssBackupComponents->PreRestore returned 0x%08X\n", hr); + errno = b_errno_win32; + return false; + } + WaitAndCheckForAsyncOperation(pAsync1.p); + /* get latest info about writer status */ + if (!CheckWriterStatus()) { + Dmsg0(0, "VSSClientGeneric::InitializePostPlugin: Failed to CheckWriterstatus\n"); + errno = b_errno_win32; + return false; + } + } // We are during restore now? m_bDuringRestore = bDuringRestore; @@ -338,7 +390,6 @@ bool VSSClientGeneric::Initialize(DWORD dwContext, bool bDuringRestore) return true; } - bool VSSClientGeneric::WaitAndCheckForAsyncOperation(IVssAsync* pAsync) { // Wait until the async operation finishes @@ -479,6 +530,16 @@ bool VSSClientGeneric::CloseBackup() m_bBackupIsInitialized = false; +{ + HRESULT hr; + BSTR xml; + int fd; + + hr = pVss->SaveAsXML(&xml); + fd = open("C:\\james.xml", O_CREAT | O_WRONLY | O_TRUNC, 0777); + write(fd, xml, wcslen(xml) * sizeof(WCHAR)); + close(fd); +} if (SUCCEEDED(pVss->BackupComplete(&pAsync.p))) { // Waits for the async operation to finish and checks the result WaitAndCheckForAsyncOperation(pAsync.p); @@ -518,6 +579,32 @@ bool VSSClientGeneric::CloseBackup() return bRet; } +bool VSSClientGeneric::CloseRestore() +{ + HRESULT hr; + IVssBackupComponents* pVss = (IVssBackupComponents*) m_pVssObject; + CComPtr pAsync; + + if (!pVss) + { + errno = ENOSYS; + return false; + } + if (SUCCEEDED(hr = pVss->PostRestore(&pAsync.p))) { + // Waits for the async operation to finish and checks the result + WaitAndCheckForAsyncOperation(pAsync.p); + /* get latest info about writer status */ + if (!CheckWriterStatus()) { + errno = b_errno_win32; + return false; + } + } else { + errno = b_errno_win32; + return false; + } + return true; +} + // Query all the shadow copies in the given set void VSSClientGeneric::QuerySnapshotSet(GUID snapshotSetID) {