|
|
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2002 Microsoft Corporation
//
// Module Name:
// TaskAnalyzeCluster.cpp
//
// Description:
// CTaskAnalyzeCluster implementation.
//
// Maintained By:
// Galen Barbee (GalenB) 03-FEB-2000
//
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Include Files
//////////////////////////////////////////////////////////////////////////////
#include "Pch.h"
#include "TaskAnalyzeCluster.h"
//////////////////////////////////////////////////////////////////////////////
// Constant Definitions
//////////////////////////////////////////////////////////////////////////////
DEFINE_THISCLASS( "CTaskAnalyzeCluster" )
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CTaskAnalyzeCluster class
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::S_HrCreateInstance
//
// Description:
// Create a CTaskAnalyzeCluster instance.
//
// Arguments:
// ppunkOut
//
// Return Values:
// S_OK
// Success.
//
// Other HRESULT as failure.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT CTaskAnalyzeCluster::S_HrCreateInstance( IUnknown ** ppunkOut ) { TraceFunc( "" ); Assert( ppunkOut != NULL );
HRESULT hr = S_OK; CTaskAnalyzeCluster * ptac = NULL;
if ( ppunkOut == NULL ) { hr = THR( E_POINTER ); goto Cleanup; } // if:
ptac = new CTaskAnalyzeCluster; if ( ptac == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if:
hr = THR( ptac->HrInit() ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
hr = THR( ptac->TypeSafeQI( IUnknown, ppunkOut ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
Cleanup:
if ( ptac != NULL ) { ptac->Release(); } // if:
HRETURN( hr );
} //*** CTaskAnalyzeCluster::S_HrCreateInstance
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::CTaskAnalyzeCluster
//
// Description:
// Constructor
//
// Arguments:
// None.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
CTaskAnalyzeCluster::CTaskAnalyzeCluster( void ) { TraceFunc( "" );
TraceFuncExit();
} //*** CTaskAnalyzeCluster::CTaskAnalyzeCluster
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::~CTaskAnalyzeCluster
//
// Description:
// Destructor
//
// Arguments:
// None.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
CTaskAnalyzeCluster::~CTaskAnalyzeCluster( void ) { TraceFunc( "" );
TraceFuncExit();
} //*** CTaskAnalyzeCluster::~CTaskAnalyzeCluster
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CTaskAnalyzeCluster - IUknkown interface.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::QueryInterface
//
// Description:
// Query this object for the passed in interface.
//
// Arguments:
// riidIn
// Id of interface requested.
//
// ppvOut
// Pointer to the requested interface.
//
// Return Value:
// S_OK
// If the interface is available on this object.
//
// E_NOINTERFACE
// If the interface is not available.
//
// E_POINTER
// ppvOut was NULL.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CTaskAnalyzeCluster::QueryInterface( REFIID riidIn , LPVOID * ppvOut ) { TraceQIFunc( riidIn, ppvOut );
HRESULT hr = S_OK;
//
// Validate arguments.
//
Assert( ppvOut != NULL ); if ( ppvOut == NULL ) { hr = THR( E_POINTER ); goto Cleanup; } // if:
//
// Handle known interfaces.
//
if ( IsEqualIID( riidIn, IID_IUnknown ) ) { *ppvOut = static_cast< ITaskAnalyzeCluster * >( this ); } // if: IUnknown
else if ( IsEqualIID( riidIn, IID_ITaskAnalyzeCluster ) ) { *ppvOut = TraceInterface( __THISCLASS__, ITaskAnalyzeCluster, this, 0 ); } // else if: ITaskAnalyzeCluster
else if ( IsEqualIID( riidIn, IID_IDoTask ) ) { *ppvOut = TraceInterface( __THISCLASS__, IDoTask, this, 0 ); } // else if: IDoTask
else if ( IsEqualIID( riidIn, IID_IClusCfgCallback ) ) { *ppvOut = TraceInterface( __THISCLASS__, IClusCfgCallback, this, 0 ); } // else if: IClusCfgCallback
else if ( IsEqualIID( riidIn, IID_INotifyUI ) ) { *ppvOut = TraceInterface( __THISCLASS__, INotifyUI, this, 0 ); } // else if: INotifyUI
else { *ppvOut = NULL; hr = E_NOINTERFACE; } // else:
//
// Add a reference to the interface if successful.
//
if ( SUCCEEDED( hr ) ) { ((IUnknown *) *ppvOut)->AddRef(); } // if: success
Cleanup:
QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
} //*** CTaskAnalyzeCluster::QueryInterface
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::AddRef
//
// Description:
// Increment the reference count of this object by one.
//
// Arguments:
// None.
//
// Return Value:
// The new reference count.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG ) CTaskAnalyzeCluster::AddRef( void ) { TraceFunc( "[IUnknown]" );
ULONG c = UlAddRef();
CRETURN( c );
} //*** CTaskAnalyzeCluster::AddRef
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::Release
//
// Description:
// Decrement the reference count of this object by one.
//
// Arguments:
// None.
//
// Return Value:
// The new reference count.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG ) CTaskAnalyzeCluster::Release( void ) { TraceFunc( "[IUnknown]" );
ULONG c = UlRelease();
CRETURN( c );
} //*** CTaskAnalyzeCluster::Release
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CTaskAnalyzeCluster - IDoTask/ITaskAnalyzeCluster interface.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::BeginTask
//
// Description:
// Task entry point.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success
//
// HRESULT failure.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CTaskAnalyzeCluster::BeginTask( void ) { TraceFunc( "[IDoTask]" );
HRESULT hr = THR( HrBeginTask() );
HRETURN( hr );
} //*** CTaskAnalyzeCluster::BeginTask
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::StopTask
//
// Description:
// Stop task entry point.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success
//
// HRESULT failure.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CTaskAnalyzeCluster::StopTask( void ) { TraceFunc( "[IDoTask]" );
HRESULT hr = THR( HrStopTask() );
HRETURN( hr );
} //*** CTaskAnalyzeCluster::StopTask
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::SetJoiningMode
//
// Description:
// Tell this task whether we are joining nodes to the cluster?
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success
//
// HRESULT failure.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CTaskAnalyzeCluster::SetJoiningMode( void ) { TraceFunc( "[ITaskAnalyzeCluster]" );
HRESULT hr = THR( HrSetJoiningMode() );
HRETURN( hr );
} //*** CTaskAnalyzeCluster::SetJoiningMode
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::SetCookie
//
// Description:
// Receive the completion cookier from the task creator.
//
// Arguments:
// cookieIn
// The completion cookie to send back to the creator when this
// task is complete.
//
// Return Value:
// S_OK
// Success
//
// HRESULT failure.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CTaskAnalyzeCluster::SetCookie( OBJECTCOOKIE cookieIn ) { TraceFunc( "[ITaskAnalyzeCluster]" );
HRESULT hr = THR( HrSetCookie( cookieIn ) );
HRETURN( hr );
} //*** CTaskAnalyzeCluster::SetCookie
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::SetClusterCookie
//
// Description:
// Receive the object manager cookie of the cluster that we are going
// to analyze.
//
// Arguments:
// cookieClusterIn
// The cookie for the cluster to work on.
//
// Return Value:
// S_OK
// Success
//
// HRESULT failure.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CTaskAnalyzeCluster::SetClusterCookie( OBJECTCOOKIE cookieClusterIn ) { TraceFunc( "[ITaskAnalyzeCluster]" );
HRESULT hr = THR( HrSetClusterCookie( cookieClusterIn ) );
HRETURN( hr );
} //*** CTaskAnalyzeCluster::SetClusterCookie
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::HrCompareDriveLetterMappings
//
// Description:
// Compare the drive letter mappings on each node to make sure there
// are no conflicts. Specifically, verify that the system disk on each
// node does not conflict with storage devices that could be failed over
// to that node.
//
// Arguments:
// None.
//
// Return Values:
// S_OK - Operation completed successfully.
// Other HRESULTs.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT CTaskAnalyzeCluster::HrCompareDriveLetterMappings( void ) { TraceFunc( "" );
HRESULT hr = S_OK; HRESULT hrDriveConflictError = S_OK; HRESULT hrDriveConflictWarning = S_OK; OBJECTCOOKIE cookieDummy; OBJECTCOOKIE cookieClusterNode; DWORD idxCurrentNode; DWORD cNodes; ULONG celtDummy; int idxDLM; BSTR bstrOuterNodeName = NULL; BSTR bstrInnerNodeName = NULL; BSTR bstrMsg = NULL; BSTR bstrMsgREF = NULL; IUnknown * punk = NULL; IEnumCookies * pecNodes = NULL; IClusCfgNodeInfo * pccniOuter = NULL; IClusCfgNodeInfo * pccniInner = NULL; SDriveLetterMapping dlmOuter; SDriveLetterMapping dlmInner;
hr = THR( HrSendStatusReport( CTaskAnalyzeClusterBase::m_bstrClusterName , TASKID_Major_Check_Cluster_Feasibility , TASKID_Minor_Check_DriveLetter_Mappings , 0 , 1 , 0 , hr , IDS_TASKID_MINOR_CHECK_DRIVELETTER_MAPPINGS ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
//
// Get the node cookie enumerator.
//
hr = THR( CTaskAnalyzeClusterBase::m_pom->FindObject( CLSID_NodeType, CTaskAnalyzeClusterBase::m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CompareDriveLetterMappings_Find_Object, hr ); goto Cleanup; }
hr = THR( punk->TypeSafeQI( IEnumCookies, &pecNodes ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CompareDriveLetterMappings_Find_Object_QI, hr ); goto Cleanup; }
//pecNodes = TraceInterface( L"CTaskAnalyzeCluster!IEnumCookies", IEnumCookies, pecNodes, 1 );
punk->Release(); punk = NULL;
//
// If there is only one node, just exit this function.
//
hr = THR( pecNodes->Count( &cNodes ) ); if ( FAILED( hr ) ) { goto Cleanup; } if ( cNodes == 1 ) { goto Cleanup; }
//
// Loop through the enumerator to compare each node with every other node.
// This requires an outer loop and an inner loop.
//
for ( idxCurrentNode = 0 ;; idxCurrentNode++ ) { //
// Cleanup.
//
if ( pccniOuter != NULL ) { pccniOuter->Release(); pccniOuter = NULL; } TraceSysFreeString( bstrOuterNodeName ); bstrOuterNodeName = NULL;
//
// Skip to the next node. This is necessary since there is only one
// enumerator for both the outer and inner loop.
//
if ( idxCurrentNode > 0 ) { // Reset back to the first item in the enumerator.
hr = STHR( pecNodes->Reset() ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Reset_Node_Enumerator, hr ); goto Cleanup; }
// Skip to the current node.
hr = STHR( pecNodes->Skip( idxCurrentNode ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Skip_To_Node, hr ); goto Cleanup; } if ( hr == S_FALSE ) { //
// Reached the end of the list.
//
hr = S_OK; break; } } // if: not at first node
//
// Find the next node.
//
hr = STHR( pecNodes->Next( 1, &cookieClusterNode, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Find_Outer_Node_Next, hr ); goto Cleanup; } if ( hr == S_FALSE ) { //
// Reached the end of the list.
//
hr = S_OK; break; }
//
// Retrieve the node information.
//
hr = THR( CTaskAnalyzeClusterBase::m_pom->GetObject( DFGUID_NodeInformation, cookieClusterNode, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Outer_NodeInfo_FindObject, hr ); goto Cleanup; }
hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccniOuter ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Outer_NodeInfo_FindObject_QI, hr ); goto Cleanup; }
//pccniOuter = TraceInterface( L"CTaskAnalyzeCluster!IClusCfgNodeInfo", IClusCfgNodeInfo, pccni, 1 );
punk->Release(); punk = NULL;
//
// Get the drive letter mappings for the outer node.
//
hr = THR( pccniOuter->GetDriveLetterMappings( &dlmOuter ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Outer_NodeInfo_GetDLM, hr ); goto Cleanup; }
//
// Get the name of the node.
//
hr = THR( pccniOuter->GetName( &bstrOuterNodeName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Outer_GetNodeName, hr ); goto Cleanup; }
TraceMemoryAddBSTR( bstrOuterNodeName );
//
// Loop through all the other nodes in the cluster.
//
for ( ;; ) { //
// Cleanup.
//
if ( pccniInner != NULL ) { pccniInner->Release(); pccniInner = NULL; } TraceSysFreeString( bstrInnerNodeName ); bstrInnerNodeName = NULL;
//
// Find the next node.
//
hr = STHR( pecNodes->Next( 1, &cookieClusterNode, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Find_Inner_Node_Next, hr ); goto Cleanup; } if ( hr == S_FALSE ) { //
// Reached the end of the list.
//
hr = S_OK; break; }
//
// Retrieve the node information.
//
hr = THR( CTaskAnalyzeClusterBase::m_pom->GetObject( DFGUID_NodeInformation, cookieClusterNode, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Inner_NodeInfo_FindObject, hr ); goto Cleanup; }
hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccniInner ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Inner_NodeInfo_FindObject_QI, hr ); goto Cleanup; }
//pccniInner = TraceInterface( L"CTaskAnalyzeCluster!IClusCfgNodeInfo", IClusCfgNodeInfo, pccni, 1 );
punk->Release(); punk = NULL;
//
// Get the drive letter mappings for the inner node.
//
hr = THR( pccniInner->GetDriveLetterMappings( &dlmInner ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Inner_NodeInfo_GetDLM, hr ); goto Cleanup; }
//
// Get the name of the node.
//
hr = THR( pccniInner->GetName( &bstrInnerNodeName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Inner_GetNodeName, hr ); goto Cleanup; }
TraceMemoryAddBSTR( bstrInnerNodeName );
//
// Loop through the drive letter mappings to make sure that there
// are no conflicts between the two machines.
//
for ( idxDLM = 0 ; idxDLM < 26 ; idxDLM++ ) { if ( dlmOuter.dluDrives[ idxDLM ] == dluSYSTEM ) { CLSID clsidMinorId; hr = THR( CoCreateGuid( &clsidMinorId ) ); if ( FAILED( hr ) ) { clsidMinorId = IID_NULL; }
switch ( dlmInner.dluDrives[ idxDLM ] ) { case dluFIXED_DISK: case dluREMOVABLE_DISK: { LPCWSTR pwszMsg; LPCWSTR pwszMsgREF;
hrDriveConflictError = HRESULT_FROM_WIN32( ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT );
hr = THR( HrFormatStringIntoBSTR( g_hInstance , IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_ERROR , &bstrMsg , bstrOuterNodeName , L'A' + idxDLM // construct the drive letter
, bstrInnerNodeName ) ); if ( bstrMsg == NULL ) { pwszMsg = L"System drive conflicts."; } else { pwszMsg = bstrMsg; }
hr = THR( HrFormatStringIntoBSTR( g_hInstance , IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_ERROR_REF , &bstrMsgREF ) ); if ( bstrMsgREF == NULL ) { pwszMsgREF = L"System drive conflicts. Make sure there is no drive letter conflict between these nodes and re-run the cluster setup."; } else { pwszMsgREF = bstrMsgREF; }
hr = THR( SendStatusReport( CTaskAnalyzeClusterBase::m_bstrClusterName , TASKID_Minor_Check_DriveLetter_Mappings , clsidMinorId , 0 , 1 , 1 , hrDriveConflictError , pwszMsg , NULL , pwszMsgREF ) ); if ( FAILED( hr ) ) { goto Cleanup; }
break; } // case: fixed disk or removable disk
case dluCOMPACT_DISC: case dluNETWORK_DRIVE: case dluRAM_DISK: { LPCWSTR pwszMsg; LPCWSTR pwszMsgREF; UINT ids = 0;
hrDriveConflictWarning = MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT );
if ( dlmInner.dluDrives[ idxDLM ] == dluCOMPACT_DISC ) { ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_CD_WARNING; } // if: ( dlmInner.dluDrives[ idxDLM ] == dluCOMPACT_DISC )
else if ( dlmInner.dluDrives[ idxDLM ] == dluNETWORK_DRIVE ) { ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_NET_WARNING; } // if: ( dlmInner.dluDrives[ idxDLM ] == dluNETWORK_DRIVE )
else if ( dlmInner.dluDrives[ idxDLM ] == dluRAM_DISK ) { ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_RAM_WARNING; } // if: ( dlmInner.dluDrives[ idxDLM ] == dluRAM_DISK )
Assert( ids != 0 );
hr = THR( HrFormatStringIntoBSTR( g_hInstance , ids , &bstrMsg , bstrOuterNodeName , L'A' + idxDLM // construct the drive letter
, bstrInnerNodeName ) ); if ( FAILED( hr ) ) { goto Cleanup; }
if ( bstrMsg == NULL ) { pwszMsg = L"System drive conflicts."; } else { pwszMsg = bstrMsg; }
hr = THR( HrFormatStringIntoBSTR( g_hInstance , IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_WARNING_REF , &bstrMsgREF ) ); if ( FAILED( hr ) ) { goto Cleanup; }
if ( bstrMsgREF == NULL ) { pwszMsgREF = L"System drive conflicts. It is recommended not to have any drive letter conflicts between nodes."; } else { pwszMsgREF = bstrMsgREF; }
hr = THR( SendStatusReport( CTaskAnalyzeClusterBase::m_bstrClusterName , TASKID_Minor_Check_DriveLetter_Mappings , clsidMinorId , 0 , 1 , 1 , hrDriveConflictWarning , pwszMsg , NULL , pwszMsgREF ) ); if ( FAILED( hr ) ) { goto Cleanup; }
break; } // case: compact disc, network drive, or ram disk
} // switch: inner drive letter usage
} // if: outer node drive is a system drive
if ( dlmInner.dluDrives[ idxDLM ] == dluSYSTEM ) { CLSID clsidMinorId; hr = THR( CoCreateGuid( &clsidMinorId ) ); if ( FAILED( hr ) ) { clsidMinorId = IID_NULL; }
switch ( dlmOuter.dluDrives[ idxDLM ] ) { case dluFIXED_DISK: case dluREMOVABLE_DISK: { LPCWSTR pwszMsg; LPCWSTR pwszMsgREF;
hrDriveConflictError = HRESULT_FROM_WIN32( ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT );
hr = THR( HrFormatStringIntoBSTR( g_hInstance , IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_ERROR , &bstrMsg , bstrInnerNodeName , L'A' + idxDLM // construct the drive letter
, bstrOuterNodeName ) ); if ( bstrMsg == NULL ) { pwszMsg = L"System drive conflicts."; } else { pwszMsg = bstrMsg; }
hr = THR( HrFormatStringIntoBSTR( g_hInstance , IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_ERROR_REF , &bstrMsgREF ) ); if ( bstrMsgREF == NULL ) { pwszMsgREF = L"System drive conflicts. Make sure there is no drive letter conflict between these nodes and re-run the cluster setup."; } else { pwszMsgREF = bstrMsgREF; }
hr = THR( SendStatusReport( CTaskAnalyzeClusterBase::m_bstrClusterName , TASKID_Minor_Check_DriveLetter_Mappings , clsidMinorId , 0 , 1 , 1 , hrDriveConflictError , pwszMsg , NULL , pwszMsgREF ) ); if ( FAILED( hr ) ) { goto Cleanup; }
break; } // case: fixed disk or removable disk
case dluCOMPACT_DISC: case dluNETWORK_DRIVE: case dluRAM_DISK: { LPCWSTR pwszMsg; LPCWSTR pwszMsgREF; UINT ids = 0;
hrDriveConflictWarning = MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT );
if ( dlmOuter.dluDrives[ idxDLM ] == dluCOMPACT_DISC ) { ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_CD_WARNING; } // if: ( dlmOuter.dluDrives[ idxDLM ] == dluCOMPACT_DISC )
else if ( dlmOuter.dluDrives[ idxDLM ] == dluNETWORK_DRIVE ) { ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_NET_WARNING; } // if: ( dlmOuter.dluDrives[ idxDLM ] == dluNETWORK_DRIVE )
else if ( dlmOuter.dluDrives[ idxDLM ] == dluRAM_DISK ) { ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_RAM_WARNING; } // if: ( dlmOuter.dluDrives[ idxDLM ] == dluRAM_DISK )
Assert( ids != 0 );
hr = THR( HrFormatStringIntoBSTR( g_hInstance , ids , &bstrMsg , bstrInnerNodeName , L'A' + idxDLM // construct the drive letter
, bstrOuterNodeName ) ); if ( FAILED( hr ) ) { goto Cleanup; }
if ( bstrMsg == NULL ) { pwszMsg = L"System drive conflicts."; } else { pwszMsg = bstrMsg; }
hr = THR( HrFormatStringIntoBSTR( g_hInstance , IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_WARNING_REF , &bstrMsgREF ) ); if ( FAILED( hr ) ) { goto Cleanup; }
if ( bstrMsgREF == NULL ) { pwszMsgREF = L"System drive conflicts. It is recommended not to have any drive letter conflicts between nodes."; } else { pwszMsgREF = bstrMsgREF; }
hr = THR( SendStatusReport( CTaskAnalyzeClusterBase::m_bstrClusterName , TASKID_Minor_Check_DriveLetter_Mappings , clsidMinorId , 0 , 1 , 1 , hrDriveConflictWarning , pwszMsg , NULL , pwszMsgREF ) ); if ( FAILED( hr ) ) { goto Cleanup; }
break; } // case: compact disc, network drive, or ram disk
} // switch: outer drive letter usage
} // if: inner node drive is a system drive
} // for: each drive letter mapping
} // for ever: inner node loop
} // for ever: outer node loop
Cleanup:
THR( HrSendStatusReport( CTaskAnalyzeClusterBase::m_bstrClusterName , TASKID_Major_Check_Cluster_Feasibility , TASKID_Minor_Check_DriveLetter_Mappings , 0 , 1 , 1 , hr , IDS_TASKID_MINOR_CHECK_DRIVELETTER_MAPPINGS ) );
TraceSysFreeString( bstrOuterNodeName ); TraceSysFreeString( bstrInnerNodeName ); TraceSysFreeString( bstrMsg ); TraceSysFreeString( bstrMsgREF );
if ( pecNodes != NULL ) { pecNodes->Release(); }
if ( pccniOuter != NULL ) { pccniOuter->Release(); }
if ( pccniInner != NULL ) { pccniInner->Release(); }
if ( punk != NULL ) { punk->Release(); }
//
// Set the return value if an error or warning occurred.
// An error will override a warning.
//
if ( hrDriveConflictError != S_OK ) { hr = hrDriveConflictError; } else if ( hrDriveConflictWarning != S_OK ) { hr = hrDriveConflictWarning; }
HRETURN( hr );
} //*** CTaskAnalyzeCluster::HrCompareDriveLetterMappings
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::HrCreateNewResourceInCluster
//
// Description:
// Create a new resource in the cluster configuration since there was
// not a match to the resource already in the cluster.
//
// Arguments:
// pccmriIn
//
// Return Value:
// S_OK
// Success.
//
// Other HRESULT error.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT CTaskAnalyzeCluster::HrCreateNewResourceInCluster( IClusCfgManagedResourceInfo * pccmriIn , BSTR bstrNodeResNameIn , BSTR * pbstrNodeResUIDInout , BSTR bstrNodeNameIn ) { TraceFunc( "" ); Assert( pccmriIn != NULL ); Assert( pbstrNodeResUIDInout != NULL );
HRESULT hr = S_OK; IClusCfgManagedResourceInfo * pccmriNew = NULL;
//
// Need to create a new object.
//
hr = THR( HrCreateNewManagedResourceInClusterConfiguration( pccmriIn, &pccmriNew ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
//
// Display the name of the node's resource in the log.
//
LogMsg( L"[MT] Created object for resource '%ws' ('%ws') from node '%ws' in the cluster configuration." , bstrNodeResNameIn , *pbstrNodeResUIDInout , bstrNodeNameIn );
//
// If this is the quorum resource, remember it.
//
hr = STHR( pccmriNew->IsQuorumResource() ); if ( hr == S_OK ) { //
// Remember the quorum device's UID.
//
Assert( m_bstrQuorumUID == NULL ); m_bstrQuorumUID = *pbstrNodeResUIDInout; *pbstrNodeResUIDInout = NULL; } // if:
hr = S_OK;
Cleanup:
if ( pccmriNew != NULL ) { pccmriNew->Release(); } // if:
HRETURN( hr );
} //*** CTaskAnalyzeCluster::HrCreateNewResourceInCluster
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::HrCreateNewResourceInCluster
//
// Description:
// Create a new resource in the cluster configuration since there was
// not a match to the resource already in the cluster.
//
// Arguments:
// pccmriIn
// The source object.
//
// ppccmriOut
// The new object that was created.
//
// Return Value:
// S_OK
// Success.
//
// Other HRESULT error.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT CTaskAnalyzeCluster::HrCreateNewResourceInCluster( IClusCfgManagedResourceInfo * pccmriIn , IClusCfgManagedResourceInfo ** ppccmriOut ) { TraceFunc( "" ); Assert( pccmriIn != NULL ); Assert( ppccmriOut != NULL );
HRESULT hr = S_OK;
//
// Need to create a new object.
//
hr = THR( HrCreateNewManagedResourceInClusterConfiguration( pccmriIn, ppccmriOut ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
//
// If the resource is manageable in a cluster then we should set it
// to be managed so it will be created by PostConfig.
//
hr = STHR( (*ppccmriOut)->IsManagedByDefault() ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
if ( hr == S_OK ) { hr = THR( (*ppccmriOut)->SetManaged( TRUE ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
} // if:
hr = S_OK;
Cleanup:
HRETURN( hr );
} //*** CTaskAnalyzeCluster::HrCreateNewResourceInCluster
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::HrFixupErrorCode
//
// Description:
// Do any fix ups needed for the passed in error code and return the
// fixed up value. The default implementation is to do no fixups.
//
// Arguments:
// hrIn
// The error code to fix up.
//
// Return Value:
// The passed in error code.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT CTaskAnalyzeCluster::HrFixupErrorCode( HRESULT hrIn ) { TraceFunc( "" );
HRETURN( hrIn );
} //*** CTaskAnalyzeCluster::HrFixupErrorCode
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::GetNodeCannotVerifyQuorumStringRefId
//
// Description:
// Return the correct string ids for the message that is displayed
// to the user when there isn't a quorum resource.
//
// Arguments:
// pdwRefIdOut
// The reference text to show the user.
//
// Return Value:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void CTaskAnalyzeCluster::GetNodeCannotVerifyQuorumStringRefId( DWORD * pdwRefIdOut ) { TraceFunc( "" ); Assert( pdwRefIdOut != NULL );
*pdwRefIdOut = IDS_TASKID_MINOR_NODE_CANNOT_ACCESS_QUORUM_ERROR_REF;
TraceFuncExit();
} //*** CTaskAnalyzeCluster::GetNodeCannotVerifyQuorumStringRefId
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::GetNoCommonQuorumToAllNodesStringIds
//
// Description:
// Return the correct string ids for the message that is displayed
// to the user when there isn't a common to all nodes quorum resource.
//
// Arguments:
// pdwMessageIdOut
// The message to show the user.
//
// pdwRefIdOut
// The reference text to show the user.
//
// Return Value:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void CTaskAnalyzeCluster::GetNoCommonQuorumToAllNodesStringIds( DWORD * pdwMessageIdOut , DWORD * pdwRefIdOut ) { TraceFunc( "" ); Assert( pdwMessageIdOut != NULL ); Assert( pdwRefIdOut != NULL );
*pdwMessageIdOut = IDS_TASKID_MINOR_MISSING_COMMON_QUORUM_RESOURCE_ERROR; *pdwRefIdOut = IDS_TASKID_MINOR_MISSING_COMMON_QUORUM_RESOURCE_ERROR_REF;
TraceFuncExit();
} //*** CTaskAnalyzeCluster::GetNoCommonQuorumToAllNodesStringIds
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::HrShowLocalQuorumWarning
//
// Description:
// Send the warning about forcing local quorum to the UI.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// The SSR was done properly.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT CTaskAnalyzeCluster::HrShowLocalQuorumWarning( void ) { TraceFunc( "" );
HRESULT hr = S_OK;
hr = THR( HrSendStatusReport( CTaskAnalyzeClusterBase::m_bstrClusterName , TASKID_Minor_Finding_Common_Quorum_Device , TASKID_Minor_Forced_Local_Quorum , 1 , 1 , 1 , MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_WIN32, ERROR_QUORUM_DISK_NOT_FOUND ) , IDS_TASKID_MINOR_FORCED_LOCAL_QUORUM ) );
HRETURN( hr );
} //*** CTaskAnalyzeCluster::HrShowLocalQuorumWarning
|