Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

398 lines
12 KiB

//////////////////////////////////////////////////////////////////////////////
//
// 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()