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.
453 lines
14 KiB
453 lines
14 KiB
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1999-2001 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// CBaseClusterForm.cpp
|
|
//
|
|
// Description:
|
|
// Contains the definition of the CBaseClusterForm class.
|
|
//
|
|
// Maintained By:
|
|
// David Potter (DavidP) 14-JUN-2001
|
|
// Vij Vasu (Vvasu) 08-MAR-2000
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Include Files
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// The precompiled header.
|
|
#include "Pch.h"
|
|
|
|
// The header file of this class.
|
|
#include "CBaseClusterForm.h"
|
|
|
|
// For the CClusSvcAccountConfig action
|
|
#include "CClusSvcAccountConfig.h"
|
|
|
|
// For the CClusNetCreate action
|
|
#include "CClusNetCreate.h"
|
|
|
|
// For the CClusDiskForm action
|
|
#include "CClusDiskForm.h"
|
|
|
|
// For the CClusDBForm action
|
|
#include "CClusDBForm.h"
|
|
|
|
// For the CClusSvcCreate action
|
|
#include "CClusSvcCreate.h"
|
|
|
|
// For the CNodeConfig action
|
|
#include "CNodeConfig.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Macros definitions
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// The minimum amount of free space in bytes, required by the
|
|
// localquorum resource (5 Mb)
|
|
#define LOCALQUORUM_MIN_FREE_DISK_SPACE 5242880
|
|
|
|
// Name of the file system required by the local quorum resource
|
|
#define LOCALQUORUM_FILE_SYSTEM L"NTFS"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CBaseClusterForm::CBaseClusterForm
|
|
//
|
|
// Description:
|
|
// Constructor of the CBaseClusterForm class.
|
|
//
|
|
// This function also stores the parameters that are required for
|
|
// creating a cluster.
|
|
//
|
|
// Arguments:
|
|
// pbcaiInterfaceIn
|
|
// Pointer to the interface class for this library.
|
|
//
|
|
// pszClusterNameIn
|
|
// Name of the cluster to be formed.
|
|
//
|
|
// pcccServiceAccountIn
|
|
// Specifies the account to be used as the cluster service account.
|
|
//
|
|
// dwClusterIPAddressIn
|
|
// dwClusterIPSubnetMaskIn
|
|
// pszClusterIPNetworkIn
|
|
// Specifies the IP address and network of the cluster IP address.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CConfigError
|
|
// If the OS version is incorrect or if the installation state
|
|
// of the cluster binaries is wrong.
|
|
//
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CBaseClusterForm::CBaseClusterForm(
|
|
CBCAInterface * pbcaiInterfaceIn
|
|
, const WCHAR * pcszClusterNameIn
|
|
, const WCHAR * pszClusterBindingStringIn
|
|
, IClusCfgCredentials * pcccServiceAccountIn
|
|
, DWORD dwClusterIPAddressIn
|
|
, DWORD dwClusterIPSubnetMaskIn
|
|
, const WCHAR * pszClusterIPNetworkIn
|
|
)
|
|
: BaseClass(
|
|
pbcaiInterfaceIn
|
|
, pcszClusterNameIn
|
|
, pszClusterBindingStringIn
|
|
, pcccServiceAccountIn
|
|
, dwClusterIPAddressIn
|
|
)
|
|
, m_dwClusterIPAddress( dwClusterIPAddressIn )
|
|
, m_dwClusterIPSubnetMask( dwClusterIPSubnetMaskIn )
|
|
, m_strClusterIPNetwork( pszClusterIPNetworkIn )
|
|
|
|
{
|
|
TraceFunc( "" );
|
|
LogMsg( "[BC] The current cluster configuration task is: Create a Cluster." );
|
|
|
|
CStatusReport srInitForm(
|
|
PBcaiGetInterfacePointer()
|
|
, TASKID_Major_Configure_Cluster_Services
|
|
, TASKID_Minor_Initializing_Cluster_Form
|
|
, 0, 1
|
|
, IDS_TASK_FORM_INIT
|
|
);
|
|
|
|
// Send the next step of this status report.
|
|
srInitForm.SendNextStep( S_OK );
|
|
|
|
//
|
|
// Write parameters to log file.
|
|
//
|
|
LogMsg(
|
|
"[BC] Cluster IP Address => %d.%d.%d.%d"
|
|
, ( m_dwClusterIPAddress & 0x000000FF )
|
|
, ( m_dwClusterIPAddress & 0x0000FF00 ) >> 8
|
|
, ( m_dwClusterIPAddress & 0x00FF0000 ) >> 16
|
|
, ( m_dwClusterIPAddress & 0xFF000000 ) >> 24
|
|
);
|
|
|
|
LogMsg(
|
|
"[BC] Subnet Mask => %d.%d.%d.%d"
|
|
, ( m_dwClusterIPSubnetMask & 0x000000FF )
|
|
, ( m_dwClusterIPSubnetMask & 0x0000FF00 ) >> 8
|
|
, ( m_dwClusterIPSubnetMask & 0x00FF0000 ) >> 16
|
|
, ( m_dwClusterIPSubnetMask & 0xFF000000 ) >> 24
|
|
);
|
|
|
|
LogMsg( "[BC] Cluster IP Network name => '%s'", m_strClusterIPNetwork.PszData() );
|
|
|
|
|
|
//
|
|
// Perform a sanity check on the parameters used by this class
|
|
//
|
|
if ( ( pszClusterIPNetworkIn == NULL ) || ( *pszClusterIPNetworkIn == L'\0' ) )
|
|
{
|
|
LogMsg( "[BC] The cluster IP Network name is invalid. Throwing an exception." );
|
|
THROW_CONFIG_ERROR( THR( E_INVALIDARG ), IDS_ERROR_INVALID_IP_NET );
|
|
} // if: the cluster IP network name is empty
|
|
|
|
|
|
//
|
|
// Make sure that there is enough free space under the cluster directory.
|
|
// The quorum logs for the localquorum resource will be under this directory.
|
|
//
|
|
{
|
|
BOOL fSuccess;
|
|
ULARGE_INTEGER uliFreeBytesAvailToUser;
|
|
ULARGE_INTEGER uliTotalBytes;
|
|
ULARGE_INTEGER uliTotalFree;
|
|
ULARGE_INTEGER uliRequired;
|
|
|
|
uliRequired.QuadPart = LOCALQUORUM_MIN_FREE_DISK_SPACE;
|
|
|
|
fSuccess = GetDiskFreeSpaceEx(
|
|
RStrGetClusterInstallDirectory().PszData()
|
|
, &uliFreeBytesAvailToUser
|
|
, &uliTotalBytes
|
|
, &uliTotalFree
|
|
);
|
|
|
|
if ( fSuccess == 0 )
|
|
{
|
|
DWORD sc = TW32( GetLastError() );
|
|
|
|
LogMsg( "[BC] Error %#08x occurred trying to get free disk space. Throwing an exception.", sc );
|
|
|
|
THROW_RUNTIME_ERROR(
|
|
HRESULT_FROM_WIN32( sc )
|
|
, IDS_ERROR_GETTING_FREE_DISK_SPACE
|
|
);
|
|
} // if: GetDiskFreeSpaceEx failed
|
|
|
|
LogMsg(
|
|
"[BC] Free space required = %#x%08x bytes. Available = %#x%08x bytes."
|
|
, uliRequired.HighPart
|
|
, uliRequired.LowPart
|
|
, uliFreeBytesAvailToUser.HighPart
|
|
, uliFreeBytesAvailToUser.LowPart
|
|
);
|
|
|
|
if ( uliFreeBytesAvailToUser.QuadPart < uliRequired.QuadPart )
|
|
{
|
|
LogMsg( "[BC] There isn't enough free space for the Local Quorum resource. The cluster create operation cannot proceed (throwing an exception)." );
|
|
|
|
THROW_CONFIG_ERROR(
|
|
HRESULT_FROM_WIN32( THR( ERROR_DISK_FULL ) )
|
|
, IDS_ERROR_INSUFFICIENT_DISK_SPACE
|
|
);
|
|
} // if: there isn't enough free space for localquorum.
|
|
|
|
LogMsg( "[BC] There is enough free space for the Local Quorum resource. The cluster create operation can proceed." );
|
|
}
|
|
|
|
/*
|
|
//
|
|
// KB: Vij Vasu (VVasu) 07-SEP-2000. Localquorum no longer needs NTFS disks
|
|
// The code below has been commented out since it is no longer required that
|
|
// localquorum resources use NTFS disks. This was confirmed by SunitaS.
|
|
//
|
|
|
|
//
|
|
// Make sure that the drive on which the cluster binaries are installed has NTFS
|
|
// on it. This is required by the localquorum resource.
|
|
//
|
|
{
|
|
WCHAR szVolumePathName[ MAX_PATH ];
|
|
WCHAR szFileSystemName[ MAX_PATH ];
|
|
BOOL fSuccess;
|
|
|
|
fSuccess = GetVolumePathName(
|
|
RStrGetClusterInstallDirectory().PszData()
|
|
, szVolumePathName
|
|
, ARRAYSIZE( szVolumePathName )
|
|
);
|
|
|
|
if ( fSuccess == 0 )
|
|
{
|
|
DWORD sc = TW32( GetLastError() );
|
|
|
|
LogMsg( "[BC] Error %#08x occurred trying to get file system type. The cluster create operation cannot proceed (throwing an exception).", sc );
|
|
|
|
THROW_RUNTIME_ERROR(
|
|
HRESULT_FROM_WIN32( sc )
|
|
, IDS_ERROR_GETTING_FILE_SYSTEM
|
|
);
|
|
} // if: GetVolumePathName failed
|
|
|
|
LogMsg( "[BC] The volume path name of the disk on which the cluster binaries reside is '%ws'.", szVolumePathName );
|
|
|
|
fSuccess = GetVolumeInformationW(
|
|
szVolumePathName // root directory
|
|
, NULL // volume name buffer
|
|
, 0 // length of name buffer
|
|
, NULL // volume serial number
|
|
, NULL // maximum file name length
|
|
, NULL // file system options
|
|
, szFileSystemName // file system name buffer
|
|
, ARRAYSIZE( szFileSystemName ) // length of file system name buffer
|
|
);
|
|
|
|
if ( fSuccess == 0 )
|
|
{
|
|
DWORD sc = TW32( GetLastError() );
|
|
|
|
LogMsg( "[BC] Error %#08x occurred trying to get file system type. The cluster create operation cannot proceed (throwing an exception).", sc );
|
|
|
|
THROW_RUNTIME_ERROR(
|
|
HRESULT_FROM_WIN32( sc )
|
|
, IDS_ERROR_GETTING_FILE_SYSTEM
|
|
);
|
|
} // if: GetVolumeInformation failed
|
|
|
|
LogMsg(
|
|
"[BC] The file system on '%ws' is '%ws'. Required file system is '%s'."
|
|
, szVolumePathName
|
|
, szFileSystemName
|
|
, LOCALQUORUM_FILE_SYSTEM
|
|
);
|
|
|
|
|
|
if ( NStringCchCompareNoCase( szFileSystemName, RTL_NUMBER_OF( szFileSystemName ), LOCALQUORUM_FILE_SYSTEM, RTL_NUMBER_OF( LOCALQUORUM_FILE_SYSTEM ) ) != 0 )
|
|
{
|
|
LogMsg( "[BC] LocalQuorum resource cannot be created on non-NTFS disk '%ws'. The cluster create operation cannot proceed (throwing an exception).", szVolumePathName );
|
|
|
|
// MUSTDO - must define proper HRESULT for this error. ( Vvasu - 10 Mar 2000 )
|
|
THROW_CONFIG_ERROR(
|
|
HRESULT_FROM_WIN32( TW32( ERROR_UNRECOGNIZED_MEDIA ) )
|
|
, IDS_ERROR_INCORRECT_INSTALL_STATE
|
|
);
|
|
} // if: the file system is not correct.
|
|
|
|
LogMsg( "[BC] LocalQuorum resource will be created on disk '%ws'. The cluster create operation can proceed.", szVolumePathName );
|
|
}
|
|
*/
|
|
|
|
//
|
|
// Create a list of actions to be performed.
|
|
// The order of appending actions is significant.
|
|
//
|
|
|
|
// Add the action to configure the cluster service account.
|
|
RalGetActionList().AppendAction( new CClusSvcAccountConfig( this ) );
|
|
|
|
// Add the action to create the ClusNet service.
|
|
RalGetActionList().AppendAction( new CClusNetCreate( this ) );
|
|
|
|
// Add the action to create the ClusDisk service.
|
|
RalGetActionList().AppendAction( new CClusDiskForm( this ) );
|
|
|
|
// Add the action to create the cluster database.
|
|
RalGetActionList().AppendAction( new CClusDBForm( this ) );
|
|
|
|
// Add the action to perform miscellaneous tasks.
|
|
RalGetActionList().AppendAction( new CNodeConfig( this ) );
|
|
|
|
// Add the action to create the ClusSvc service.
|
|
RalGetActionList().AppendAction( new CClusSvcCreate( this ) );
|
|
|
|
|
|
// Indicate if rollback is possible or not.
|
|
SetRollbackPossible( RalGetActionList().FIsRollbackPossible() );
|
|
|
|
// Indicate that a cluster should be formed during commit.
|
|
SetAction( eCONFIG_ACTION_FORM );
|
|
|
|
// Send the last step of a status report.
|
|
srInitForm.SendNextStep( S_OK );
|
|
|
|
LogMsg( "[BC] Initialization for creating a cluster has completed." );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CBaseClusterForm::CBaseClusterForm
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CBaseClusterForm::~CBaseClusterForm
|
|
//
|
|
// Description:
|
|
// Destructor of the CBaseClusterForm class
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// None.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CBaseClusterForm::~CBaseClusterForm( void ) throw()
|
|
{
|
|
TraceFunc( "" );
|
|
TraceFuncExit();
|
|
|
|
} //*** CBaseClusterForm::~CBaseClusterForm
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CBaseClusterForm::Commit
|
|
//
|
|
// Description:
|
|
// Create the cluster.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CRuntimeError
|
|
// If any of the APIs fail.
|
|
//
|
|
// Any exceptions thrown by functions called.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CBaseClusterForm::Commit( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
CStatusReport srFormingCluster(
|
|
PBcaiGetInterfacePointer()
|
|
, TASKID_Major_Configure_Cluster_Services
|
|
, TASKID_Minor_Commit_Forming_Node
|
|
, 0, 1
|
|
, IDS_TASK_FORMING_CLUSTER
|
|
);
|
|
|
|
LogMsg( "[BC] Initiating a cluster create operation." );
|
|
|
|
// Send the next step of this status report.
|
|
srFormingCluster.SendNextStep( S_OK );
|
|
|
|
// Call the base class commit routine. This commits the action list.
|
|
BaseClass::Commit();
|
|
|
|
// If we are here, then everything went well.
|
|
SetCommitCompleted( true );
|
|
|
|
// Send the last step of this status report.
|
|
srFormingCluster.SendLastStep( S_OK );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CBaseClusterForm::Commit
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// void
|
|
// CBaseClusterForm::Rollback
|
|
//
|
|
// Description:
|
|
// Performs the rolls back of the action committed by this object.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any exceptions thrown by functions called.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CBaseClusterForm::Rollback( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
// Rollback the actions.
|
|
BaseClass::Rollback();
|
|
|
|
SetCommitCompleted( false );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CBaseClusterForm::Rollback
|