399 lines
12 KiB
C++
399 lines
12 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1999-2000 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// CClusSvc.cpp
|
|
//
|
|
// Description:
|
|
// Contains the definition of the CClusSvc class.
|
|
//
|
|
// Maintained By:
|
|
// Vij Vasu (Vvasu) 08-MAR-2000
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Include Files
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// The precompiled header.
|
|
#include "pch.h"
|
|
|
|
// The header for this file
|
|
#include "CClusSvc.h"
|
|
|
|
// For DwRemoveDirectory()
|
|
#include "Common.h"
|
|
|
|
// To set the failure actions of the cluster service.
|
|
#include "clusrtl.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Macros
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Name of the NodeId cluster service parameter registry value.
|
|
#define CLUSSVC_NODEID_VALUE L"NodeId"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusSvc::CClusSvc()
|
|
//
|
|
// Description:
|
|
// Constructor of the CClusSvc class
|
|
//
|
|
// Arguments:
|
|
// pbcaParentActionIn
|
|
// Pointer to the base cluster action of which this action is a part.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CAssert
|
|
// If the parameters are incorrect.
|
|
//
|
|
// Any exceptions thrown by underlying functions
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CClusSvc::CClusSvc(
|
|
CBaseClusterAction * pbcaParentActionIn
|
|
)
|
|
: m_cservClusSvc( CLUSTER_SERVICE_NAME )
|
|
, m_pbcaParentAction( pbcaParentActionIn )
|
|
{
|
|
|
|
BCATraceScope( "" );
|
|
|
|
if ( m_pbcaParentAction == NULL)
|
|
{
|
|
BCATraceMsg( "Pointers to the parent action is NULL. Throwing exception." );
|
|
THROW_ASSERT(
|
|
E_INVALIDARG
|
|
, "CClusSvc::CClusSvc() => Required input pointer in NULL"
|
|
);
|
|
} // if: the parent action pointer is NULL
|
|
|
|
} //*** CClusSvc::CClusSvc()
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusSvc::~CClusSvc( void )
|
|
//
|
|
// Description:
|
|
// Destructor of the CClusSvc class.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any exceptions thrown by underlying functions
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CClusSvc::~CClusSvc( void )
|
|
{
|
|
BCATraceScope( "" );
|
|
|
|
} //*** CClusSvc::~CClusSvc()
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// void
|
|
// CClusSvc::ConfigureService()
|
|
//
|
|
// Description:
|
|
// Create the service, set the failure actions and the service account.
|
|
// Then start the service.
|
|
//
|
|
// Arguments:
|
|
// pszClusterDomainAccountNameIn
|
|
// pszClusterAccountPwdIn
|
|
// Information about the account to be used as the cluster service
|
|
// account.
|
|
//
|
|
// pszNodeIdString
|
|
// String containing the Id of this node.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
// Any that are thrown by the underlying functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusSvc::ConfigureService(
|
|
const WCHAR * pszClusterDomainAccountNameIn
|
|
, const WCHAR * pszClusterAccountPwdIn
|
|
, const WCHAR * pszNodeIdStringIn
|
|
, bool fIsVersionCheckingDisabledIn
|
|
)
|
|
{
|
|
BCATraceScope( "" );
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
CStatusReport srCreatingClusSvc(
|
|
PbcaGetParent()->PBcaiGetInterfacePointer()
|
|
, TASKID_Major_Configure_Cluster_Services
|
|
, TASKID_Minor_Creating_Cluster_Service
|
|
, 0, 2
|
|
, IDS_TASK_CREATING_CLUSSVC
|
|
);
|
|
|
|
LogMsg( "Configuring the Cluster service." );
|
|
|
|
// Send the next step of this status report.
|
|
srCreatingClusSvc.SendNextStep( S_OK );
|
|
|
|
// Create the cluster service.
|
|
m_cservClusSvc.Create( m_pbcaParentAction->HGetMainInfFileHandle() );
|
|
|
|
do
|
|
{
|
|
LogMsg( "Setting the Cluster service account information." );
|
|
|
|
|
|
// Open a smart handle to the cluster service.
|
|
SmartSCMHandle sscmhClusSvcHandle(
|
|
OpenService(
|
|
m_pbcaParentAction->HGetSCMHandle()
|
|
, CLUSTER_SERVICE_NAME
|
|
, SERVICE_CHANGE_CONFIG
|
|
)
|
|
);
|
|
|
|
|
|
if ( sscmhClusSvcHandle.FIsInvalid() )
|
|
{
|
|
dwError = TW32( GetLastError() );
|
|
BCATraceMsg( "OpenService() failed." );
|
|
break;
|
|
} // if: we could not open a handle to the cluster service.
|
|
|
|
//
|
|
// Set the service account information.
|
|
//
|
|
{
|
|
if (
|
|
ChangeServiceConfig(
|
|
sscmhClusSvcHandle
|
|
, SERVICE_NO_CHANGE
|
|
, SERVICE_NO_CHANGE
|
|
, SERVICE_NO_CHANGE
|
|
, NULL
|
|
, NULL
|
|
, NULL
|
|
, NULL
|
|
, pszClusterDomainAccountNameIn
|
|
, pszClusterAccountPwdIn
|
|
, NULL
|
|
)
|
|
== FALSE
|
|
)
|
|
{
|
|
dwError = TW32( GetLastError() );
|
|
BCATraceMsg1(
|
|
"ChangeServiceConfig() failed. Account = '%ws'."
|
|
, pszClusterDomainAccountNameIn
|
|
);
|
|
break;
|
|
} // if: we could not set the account information.
|
|
}
|
|
|
|
LogMsg( "Setting the Cluster service failure actions." );
|
|
|
|
// Set the failure actions of the cluster service service.
|
|
dwError = TW32( ClRtlSetSCMFailureActions( NULL ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
BCATraceMsg( "ClRtlSetSCMFailureActions() failed." );
|
|
break;
|
|
} // if: the service failure actions couldn't be set
|
|
|
|
LogMsg( "Setting the Cluster service parameters." );
|
|
|
|
// Send the next step of this status report.
|
|
srCreatingClusSvc.SendNextStep( S_OK );
|
|
|
|
{
|
|
CRegistryKey rkClusSvcParams;
|
|
|
|
// Open the parameters key or create it if it does not exist.
|
|
rkClusSvcParams.CreateKey(
|
|
HKEY_LOCAL_MACHINE
|
|
, CLUSREG_KEYNAME_CLUSSVC_PARAMETERS
|
|
, KEY_WRITE
|
|
);
|
|
|
|
// Set the NodeId string.
|
|
rkClusSvcParams.SetValue(
|
|
CLUSSVC_NODEID_VALUE
|
|
, REG_SZ
|
|
, reinterpret_cast< const BYTE * >( pszNodeIdStringIn )
|
|
, ( wcslen( pszNodeIdStringIn ) + 1 ) * sizeof( *pszNodeIdStringIn )
|
|
);
|
|
|
|
// If version checking has been disabled, set a flag in the service parameters
|
|
// to indicate this.
|
|
if ( fIsVersionCheckingDisabledIn )
|
|
{
|
|
DWORD dwNoVersionCheck = 1;
|
|
|
|
rkClusSvcParams.SetValue(
|
|
CLUSREG_NAME_SVC_PARAM_NOVER_CHECK
|
|
, REG_DWORD
|
|
, reinterpret_cast< const BYTE * >( &dwNoVersionCheck )
|
|
, sizeof( dwNoVersionCheck )
|
|
);
|
|
|
|
BCATraceMsg( "Cluster version checking has been disabled on this computer." );
|
|
LogMsg( "Cluster version checking has been disabled on this computer." );
|
|
} // if: version checking has been disabled
|
|
}
|
|
|
|
//
|
|
// Set the cluster installation state.
|
|
//
|
|
if ( ClRtlSetClusterInstallState( eClusterInstallStateConfigured ) == FALSE )
|
|
{
|
|
dwError = TW32( GetLastError() );
|
|
LogMsg( "Could not set the cluster installation state." );
|
|
BCATraceMsg( "Could not set the cluster installation state. Throwing exception." );
|
|
|
|
break;
|
|
} // ClRtlSetClusterInstallState() failed.
|
|
|
|
}
|
|
while( false ); // dummy do-while loop to avoid gotos
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
LogMsg( "Error %#08x occurred trying configure the ClusSvc service.", dwError );
|
|
BCATraceMsg1( "Error %#08x occurred trying configure the ClusSvc service. Throwing exception.", dwError );
|
|
THROW_RUNTIME_ERROR(
|
|
HRESULT_FROM_WIN32( dwError )
|
|
, IDS_ERROR_CLUSSVC_CONFIG
|
|
);
|
|
} // if; there was an error getting the handle.
|
|
|
|
// Send the next step of this status report.
|
|
srCreatingClusSvc.SendNextStep( S_OK );
|
|
|
|
{
|
|
UINT cQueryCount = 200;
|
|
|
|
CStatusReport srStartingClusSvc(
|
|
PbcaGetParent()->PBcaiGetInterfacePointer()
|
|
, TASKID_Major_Configure_Cluster_Services
|
|
, TASKID_Minor_Starting_Cluster_Service
|
|
, 0, cQueryCount + 2 // we will send at most cQueryCount reports while waiting for the service to start (the two extra sends are below)
|
|
, IDS_TASK_STARTING_CLUSSVC
|
|
);
|
|
|
|
// Send the next step of this status report.
|
|
srStartingClusSvc.SendNextStep( S_OK );
|
|
|
|
// Start the service.
|
|
m_cservClusSvc.Start(
|
|
m_pbcaParentAction->HGetSCMHandle()
|
|
, true // wait for the service to start
|
|
, 1500 // wait 1.5 seconds between queries for status.
|
|
, cQueryCount // query cQueryCount times
|
|
, &srStartingClusSvc // status report to be sent while waiting for the service to start
|
|
);
|
|
|
|
// Send the last step of this status report.
|
|
srStartingClusSvc.SendLastStep( S_OK );
|
|
}
|
|
|
|
} //*** CClusSvc::ConfigureService()
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// void
|
|
// CClusSvc::CleanupService( void )
|
|
//
|
|
// Description:
|
|
// Stop, cleanup and remove the service.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any that are thrown by the underlying functions.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusSvc::CleanupService( void )
|
|
{
|
|
BCATraceScope( "" );
|
|
|
|
LogMsg( "Trying to stop the Cluster Service." );
|
|
|
|
// Stop the service.
|
|
m_cservClusSvc.Stop(
|
|
m_pbcaParentAction->HGetSCMHandle()
|
|
, 5000 // wait 5 seconds between queries for status.
|
|
, 60 // query 60 times ( 5 minutes )
|
|
);
|
|
|
|
//
|
|
// Restore the cluster installation state.
|
|
//
|
|
if ( ClRtlSetClusterInstallState( eClusterInstallStateFilesCopied ) == FALSE )
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
|
|
LogMsg( "Could not set the cluster installation state." );
|
|
BCATraceMsg( "Could not set the cluster installation state. Throwing exception." );
|
|
|
|
THROW_RUNTIME_ERROR(
|
|
HRESULT_FROM_WIN32( dwError )
|
|
, IDS_ERROR_SETTING_INSTALL_STATE
|
|
);
|
|
} // ClRtlSetClusterInstallState() failed.
|
|
|
|
LogMsg( "Cleaning up Cluster Service." );
|
|
|
|
m_cservClusSvc.Cleanup( m_pbcaParentAction->HGetMainInfFileHandle() );
|
|
|
|
// Cleanup the local quorum directory.
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
const WCHAR * pcszQuorumDir = m_pbcaParentAction->RStrGetLocalQuorumDirectory().PszData();
|
|
|
|
dwError = TW32( DwRemoveDirectory( pcszQuorumDir ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
BCATraceMsg2( "The local quorum directory '%s' cannot be removed. Non-fatal error %#x occurred.\n", pcszQuorumDir, dwError );
|
|
LogMsg( "The local quorum directory '%s' cannot be removed. Non-fatal error %#x occurred.\n", pcszQuorumDir, dwError );
|
|
} // if: we could not remove the local quorum directory
|
|
}
|
|
|
|
} //*** CClusSvc::CleanupService()
|