|
|
/*++
Copyright(c) 2001 Microsoft Corporation
Module Name:
NLB Manager
File Name:
nlbhost.cpp
Abstract:
Implementation of class NLBHost
NLBHost is responsible for connecting to an NLB host and getting/setting its NLB-related configuration.
History:
03/31/01 JosephJ Created
--*/
#include "tprov.h"
#include "nlbhost.tmh"
//
// Static members of class NLBHost.
//
WSADATA NLBHost::s_WsaData; LONG NLBHost::s_InstanceCount; BOOL NLBHost::s_FatalError; BOOL NLBHost::s_WsaInitialized; BOOL NLBHost::s_ComInitialized; IWbemStatusCodeTextPtr NLBHost::s_sp_werr; // Smart pointer
WBEMSTATUS extract_GetClusterConfiguration_output_params( IN IWbemClassObjectPtr spWbemOutput, OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg );
WBEMSTATUS setup_GetClusterConfiguration_input_params( IN LPCWSTR szNic, IN IWbemClassObjectPtr spWbemInput );
WBEMSTATUS setup_UpdateClusterConfiguration_input_params( IN LPCWSTR szNic, IN PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg, IN IWbemClassObjectPtr spWbemInput );
VOID NLBHost::mfn_LogHr( LPCWSTR pwszMessage, HRESULT hr ) {
if (s_sp_werr) { BSTR bstr1 = 0; BSTR bstr2 = 0;
SCODE sc; sc = s_sp_werr->GetFacilityCodeText( hr, 0, 0, &bstr1 ); if( sc != S_OK ) { bstr2 = L"Unknown Error"; } sc = s_sp_werr->GetErrorCodeText( hr, 0, 0, &bstr2 ); if( sc != S_OK ) { bstr2 = L"Unknown Code"; } mfn_Log( L"%s %s: %s(hr=0x%08lx)", pwszMessage, (LPCWSTR) bstr1, (LPCWSTR) bstr2, hr ); SysFreeString( bstr1 ); SysFreeString( bstr2 ); } else { mfn_Log( L"%s (hr=0x%08lx)", pwszMessage, hr ); } }
VOID NLBHost::mfn_Log( LPCWSTR pwszMessage, ... ) { WCHAR wszBuffer[1024]; wszBuffer[0] = 0;
va_list arglist; va_start (arglist, pwszMessage); int cch = vswprintf(wszBuffer, pwszMessage, arglist); va_end (arglist);
m_pfnLogger(m_pLoggerContext, wszBuffer); }
NLBHost::NLBHost( const WCHAR * pBindString, const WCHAR * pFriendlyName, PFN_LOGGER pfnLogger, PVOID pLoggerContext ) /*++
Routine Description:
Constructor for NLBHost.
The constructor does not initiate any connections to the host. Connections to the host are initiated on demand (based on method calls).
Arguments:
pBindString - String used to connect to the remote host. pFriendlyName - Descriptive name of the host. Used for logging. pfnLogger - Function called to log textual information. pLoggerContext - Caller's context, passed in calls to pfnLogger --*/ { m_BindString = pBindString; // implicit copy
m_FriendlyName = pFriendlyName; // implicit copy
m_pfnLogger = pfnLogger; m_pLoggerContext = pLoggerContext;
if (InterlockedIncrement(&s_InstanceCount) == 1) { mfn_InitializeStaticFields();
}
InitializeCriticalSection(&m_Lock);
mfn_Log( L"NLBHost(BindString=%s, FriendlyName=%s) constructor succeeded.", (LPCWSTR) pBindString, (LPCWSTR) pFriendlyName ); }
NLBHost::~NLBHost() /*++
Routine Description:
Destructor for NLBHost.
--*/ { mfn_Log(L"NLBHost distructor(%s).", (LPCWSTR) m_FriendlyName);
ASSERT(m_fProcessing == FALSE); // Shouldn't be doing any processing when
// calling the distructor.
if (InterlockedDecrement(&s_InstanceCount)==0) { mfn_DeinitializeStaticFields(); } DeleteCriticalSection(&m_Lock);
}
UINT NLBHost::Ping( VOID ) { if (s_FatalError) return ERROR_INTERNAL_ERROR;
return mfn_ping(); } WBEMSTATUS NLBHost::GetHostInformation( OUT HostInformation **ppHostInfo ) { WBEMSTATUS Status; HostInformation *pHostInfo = NULL; BOOL fConnected = FALSE; NicInformation *pNicInfo=NULL;
if (s_FatalError) { Status = WBEM_E_CRITICAL_ERROR; goto end; }
pHostInfo = new HostInformation; if (pHostInfo == NULL) { Status = WBEM_E_OUT_OF_MEMORY; goto end; }
//
// Connect to the host.
//
Status = mfn_connect();
if (FAILED(Status)) goto end; fConnected = TRUE;
#if 0
//
// Now find the instance and execute the method to get the host info.
//
mfn_find_host_instance(); ... stuff parameters ... mfn_execute_method(); #endif //
pHostInfo->MachineName = L"ACME-Machine-Name";
pNicInfo = pHostInfo->nicInformation;
pNicInfo->fullNicName = L"ACME Full Nic Name"; pNicInfo->adapterGuid = L"{AD4DA14D-CAAE-42DD-97E3-5355E55247C2}"; pNicInfo->friendlyName = L"ACME Friendly Name";
pHostInfo->NumNics = 1;
end:
if (fConnected) { mfn_disconnect(); }
if (FAILED(Status)) { if (pHostInfo != NULL) { delete pHostInfo; } pHostInfo = NULL; }
*ppHostInfo = pHostInfo;
return Status; }
//
// Configuration operations:
//
WBEMSTATUS NLBHost::GetClusterConfiguration( IN const WCHAR* pNicGuid, OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; IWbemClassObjectPtr spWbemInputInstance = NULL; // smart pointer
BOOL fConnected = FALSE; LPWSTR pRelPath = NULL; IWbemClassObjectPtr spWbemOutput = NULL; // smart pointer.
ZeroMemory(pCfg, sizeof(*pCfg));
if (s_FatalError) { Status = WBEM_E_CRITICAL_ERROR; goto end; }
//
// Connect to the host.
//
Status = mfn_connect();
if (FAILED(Status)) goto end; fConnected = TRUE;
mfn_Log( L"NLBHost -- getting cluster configuration on NIC (%s).", pNicGuid );
//
// Get input instance and relpath...
//
Status = CfgUtilGetWmiInputInstanceAndRelPath( m_sp_pws, L"NlbsNic", // szClassName
L"AdapterGuid", // szParameterName
pNicGuid, // szPropertyValue
L"GetClusterConfiguration", // szMethodName,
spWbemInputInstance, // smart pointer
&pRelPath // free using delete
);
if (FAILED(Status)) { mfn_Log( L"NLBHost -- error 0x%08lx trying to find NIC instance\n", (UINT) Status ); goto end; }
//
// NOTE: spWbemInputInstance could be NULL -- in fact it is
// NULL because GetClusterConfiguration doesn't require input args
//
//
// Run the Method!
//
{ HRESULT hr;
printf("Going to call GetClusterConfiguration\n");
hr = m_sp_pws->ExecMethod( _bstr_t(pRelPath), L"GetClusterConfiguration", 0, NULL, spWbemInputInstance, &spWbemOutput, NULL ); printf("GetClusterConfiguration returns\n"); if( FAILED( hr) ) { printf("IWbemServices::ExecMethod failure 0x%08lx\n", (UINT) hr); goto end; } else { printf("GetClusterConfiguration method returns SUCCESS!\n"); }
if (spWbemOutput == NULL) { //
// Hmm --- no output ?!
//
printf("ExecMethod GetClusterConfiguration had no output\n"); Status = WBEM_E_NOT_FOUND; goto end; } }
//
// Extract all the out parameters!
//
{ DWORD dwRet=0; Status = CfgUtilGetWmiDWORDParam( spWbemOutput, L"ReturnValue", &dwRet );
if (FAILED(Status)) { printf("IWbemClassObject::Get failure\n"); //
// Let's ignore for now...
//
dwRet = 0; } Status = extract_GetClusterConfiguration_output_params( spWbemOutput, pCfg );
}
end:
if (fConnected) { mfn_disconnect(); }
if (pRelPath != NULL) { delete pRelPath; }
spWbemInputInstance = NULL; // smart pointer.
return Status;
}
WBEMSTATUS NLBHost::SetClusterConfiguration( IN const WCHAR * pNicGuid, IN const PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg, IN UINT GenerationId, OUT UINT * pRequestId ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
if (s_FatalError) { goto end; }
mfn_Log( L"NLBHost -- setting cluster configuration on NIC (%s).", pNicGuid ); *pRequestId = 123;
Status = WBEM_S_PENDING;
end:
return Status; }
WBEMSTATUS NLBHost::GetAsyncResult( IN UINT RequestId, OUT UINT * pGenerationId, OUT UINT * pResultCode, OUT _bstr_t * pResultText ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; if (s_FatalError) { goto end; }
mfn_Log( L"NLBHost -- checking result of Async operation %d\n", RequestId ); *pGenerationId = 1; *pResultCode = 1; *pResultText = L"Result"; Status = WBEM_NO_ERROR;
end:
return Status; }
WBEMSTATUS NLBHost::mfn_connect( VOID ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; HRESULT hr; _bstr_t serverPath;
hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &m_sp_pwl); if (FAILED(hr)) { mfn_LogHr(L"CoCreateInstance IWebmLocator failed", hr); m_sp_pwl = NULL; goto end; }
//
serverPath = _bstr_t(L"\\\\") + m_BindString + L"\\root\\microsoftnlb";
hr = m_sp_pwl->ConnectServer( serverPath, NULL, // strUser,
NULL, // strPassword,
NULL, 0, NULL, NULL, &m_sp_pws ); // these have been found to be special cases where retrying may help.
if( ( hr == 0x800706bf ) || ( hr == 0x80070767 ) || ( hr == 0x80070005 ) ) { int delay = 250; // milliseconds
int timesToRetry = 20; for( int i = 0; i < timesToRetry; ++i ) { Sleep(delay); mfn_Log(L"connectserver recoverable failure, retrying."); hr = m_sp_pwl->ConnectServer( serverPath, NULL, // strUser,
NULL, // strPassword,
NULL, 0, NULL, NULL, &m_sp_pws ); if( !FAILED( hr) ) { break; } } } else if ( hr == 0x80041064 ) { // trying to connect to local machine. Cannot use credentials.
mfn_Log(L"Connecting to self. Retrying without using credentials"); hr = m_sp_pwl->ConnectServer( serverPath, NULL, NULL, 0, NULL, 0, 0, &m_sp_pws ); }
if (FAILED(hr)) { mfn_LogHr(L"Error connecting to server", hr); m_sp_pws = NULL; goto end; } else { mfn_Log(L"Successfully connected to server %s", serverPath); }
// Set the proxy so that impersonation of the client occurs.
//
hr = CoSetProxyBlanket( m_sp_pws, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_NAME,
COLE_DEFAULT_PRINCIPAL, // NULL,
RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, COLE_DEFAULT_AUTHINFO, // NULL,
EOAC_DEFAULT // EOAC_NONE
);
if (FAILED(hr)) { mfn_LogHr(L"Error setting proxy blanket", hr); goto end; } else { mfn_Log(L"Successfully set up proxy settings."); }
Status = WBEM_NO_ERROR;
end: if (FAILED(Status)) { if (m_sp_pws != NULL) { // Smart pointer.
m_sp_pws = NULL; }
if (m_sp_pwl != NULL) { // Smart pointer.
m_sp_pwl = NULL; } }
return Status; }
VOID NLBHost::mfn_disconnect( VOID ) { mfn_Log(L"Disconnecting from host %s", m_BindString); if (m_sp_pws != NULL) { // Smart pointer
m_sp_pws = NULL; }
if (m_sp_pwl != NULL) { // Smart pointer
m_sp_pwl = NULL; } }
VOID NLBHost::mfn_InitializeStaticFields( VOID ) { s_FatalError = TRUE;
// Initialize com.
//
HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED); if ( FAILED(hr) ) { mfn_Log(L"Failed to initialize COM library (hr=0x%08lx)", hr); goto end; } s_ComInitialized = TRUE;
//
// Initialize Winsock
//
int err = WSAStartup(MAKEWORD(2,2), &s_WsaData); mfn_Log(L"Initializing Winsock"); err = WSAStartup(MAKEWORD(2,2), &s_WsaData); if (err) { mfn_Log(L"PING_WSASTARTUP_FAILED %d", GetLastError()); goto end; } s_WsaInitialized = TRUE; s_FatalError = FALSE;
//
// Get some WMI interface pointers...
//
SCODE sc = CoCreateInstance( CLSID_WbemStatusCodeText, 0, CLSCTX_INPROC_SERVER, IID_IWbemStatusCodeText, (LPVOID *) &s_sp_werr ); if( sc != S_OK ) { s_sp_werr = NULL; mfn_Log(L"CoCreateInstance IWbemStatusCodeText failure\n"); }
end:
if (s_FatalError) { mfn_DeinitializeStaticFields(); }
}
VOID NLBHost::mfn_DeinitializeStaticFields( VOID ) { if (s_sp_werr != NULL) { s_sp_werr = NULL; // Smart pointer
}
if (s_WsaInitialized) { mfn_Log(L"Deinitializing Winsock"); WSACleanup(); s_WsaInitialized = FALSE; }
if (s_ComInitialized) { mfn_Log(L"Deinitializing COM"); CoUninitialize(); s_ComInitialized = FALSE; } }
#if 0
WBEMSTATUS extract_extended_config_from_wmi( IN IWbemClassObjectPtr &spWbemOutput, OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg ) {
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; NLB_IP_ADDRESS_INFO *pIpInfo = NULL; UINT NumIpAddresses = 0; BOOL fNlbBound = FALSE; WLBS_REG_PARAMS NlbParams; // The WLBS-specific configuration
BOOL fNlbParamsValid = FALSE; UINT Generation = 1;
//
// Verify that pCfg is indeed zero-initialized.
// We are doing this because we want to make sure that the caller
// doesn't pass in a perviously initialized pCfg which may have a non-null
// ip address array.
//
{ BYTE *pb = (BYTE*) pCfg; BYTE *pbEnd = (BYTE*) (pCfg+1);
for (; pb < pbEnd; pb++) { if (*pb!=0) { printf(L"uninitialized pCfg\n"); ASSERT(!"uninitialized pCfg"); Status = WBEM_E_INVALID_PARAMETER; goto end; } }
}
//
// Get the ip address list.
//
Status = CfgUtilGetStaticIpAddresses( m_szNicGuid, &NumIpAddresses, &pIpInfo );
if (FAILED(Status)) { printf("Error 0x%08lx getting ip address list for %ws\n", (UINT) Status, m_szNicGuid); mfn_Log(L"Error IP Address list on this NIC\n"); pIpInfo = NULL; goto end; }
//
// TEST TEST TEST
//
if (0) { if (NumIpAddresses>1) { //
// Let's munge the 2nd IP address
//
if (!_wcsicmp(pIpInfo[1].IpAddress, L"10.0.0.33")) { wcscpy(pIpInfo[1].IpAddress, L"10.0.0.44"); } else { wcscpy(pIpInfo[1].IpAddress, L"10.0.0.33"); } } MyBreak(L"Break just before calling CfgUtilSetStaticIpAddresses\n"); Status = CfgUtilSetStaticIpAddresses( m_szNicGuid, NumIpAddresses, pIpInfo ); }
//
// Check if NLB is bound
//
Status = CfgUtilCheckIfNlbBound( m_szNicGuid, &fNlbBound ); if (FAILED(Status)) { printf("Error 0x%08lx determining if NLB is bound to %ws\n", (UINT) Status, m_szNicGuid); mfn_Log(L"Error determining if NLB is bound to this NIC\n"); goto end; }
if (fNlbBound) { //
// Get the latest NLB configuration information for this NIC.
//
Status = CfgUtilGetNlbConfig( m_szNicGuid, &NlbParams ); if (FAILED(Status)) { //
// We don't consider a catastrophic failure.
//
printf("Error 0x%08lx reading NLB configuration for %ws\n", (UINT) Status, m_szNicGuid); mfn_Log(L"Error reading NLB configuration for this NIC\n"); Status = WBEM_NO_ERROR; fNlbParamsValid = FALSE; ZeroMemory(&NlbParams, sizeof(NlbParams)); } else { fNlbParamsValid = TRUE; } }
//
// Get the current generation
//
{ BOOL fExists=FALSE; HKEY hKey = sfn_RegOpenKey( m_szNicGuid, NULL // NULL == root for this guid.,
); Generation = 1; // We assume generation is 1 on error reading gen.
if (hKey!=NULL) { LONG lRet; DWORD dwType; DWORD dwData; dwData = sizeof(Generation); lRet = RegQueryValueEx( hKey, // handle to key to query
L"Generation", // address of name of value to query
NULL, // reserved
&dwType, // address of buffer for value type
(LPBYTE) &Generation, // address of data buffer
&dwData // address of data buffer size
); if ( lRet != ERROR_SUCCESS || dwType != REG_DWORD || dwData != sizeof(Generation)) { //
// Couldn't read the generation. Let's assume it's
// a starting value of 1.
//
printf("Error reading generation for %ws; assuming its 0\n", m_szNicGuid); Generation = 1; } } }
//
// Success ... fill out pCfg
//
pCfg->fValidNlbCfg = fNlbParamsValid; pCfg->Generation = Generation; pCfg->fBound = fNlbBound; pCfg->NumIpAddresses = NumIpAddresses; pCfg->pIpAddressInfo = pIpInfo; if (fNlbBound) { pCfg->NlbParams = NlbParams; // struct copy
}
Status = WBEM_NO_ERROR;
end:
if (FAILED(Status)) { if (pIpInfo!=NULL) { delete pIpInfo; } pCfg->fValidNlbCfg = FALSE; }
return Status; return WBEM_NO_ERROR; } #endif // 0
WBEMSTATUS NlbHostGetConfiguration( IN LPCWSTR szMachine, // empty string for local
IN LPCWSTR szNicGuid, OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCurrentCfg ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; IWbemServicesPtr spWbemService = NULL; // Smart pointer
IWbemClassObjectPtr spWbemInput = NULL; // smart pointer
IWbemClassObjectPtr spWbemOutput = NULL; // smart pointer.
LPWSTR pRelPath = NULL;
//
// Get interface to the NLB namespace on the specified machine
//
{ #define _MaxLen 256
WCHAR NetworkResource[_MaxLen];
if (*szMachine == 0) { szMachine = L"."; } _snwprintf(NetworkResource, (_MaxLen-1), L"\\\\%ws\\root\\microsoftnlb", szMachine); NetworkResource[_MaxLen-1]=0;
wprintf(L"Connecting to NLB on %ws ...\n", szMachine);
Status = CfgUtilConnectToServer( NetworkResource, NULL, // szUser
NULL, // szPassword
NULL, // szAuthority (domain)
&spWbemService ); if (FAILED(Status)) { wprintf(L"ERROR: COULD NOT CONNECT TO NLB ON %ws\n", szMachine); goto end; } wprintf(L"Successfully connected to NLB on %ws...\n", szMachine); }
//
// Get wmi input instance to "GetClusterConfiguration" method
//
{ Status = CfgUtilGetWmiInputInstanceAndRelPath( spWbemService, L"NlbsNic", // szClassName
L"AdapterGuid", // szParameterName
szNicGuid, // szPropertyValue
L"GetClusterConfiguration", // szMethodName,
spWbemInput, // smart pointer
&pRelPath // free using delete
);
if (FAILED(Status)) { wprintf( L"ERROR 0x%08lx trying to get instance of GetClusterConfiguration\n", (UINT) Status ); goto end; } }
//
// Setup params for the "GetClusterConfiguration" method
// NOTE: spWbemInput could be NULL.
//
Status = setup_GetClusterConfiguration_input_params( szNicGuid, spWbemInput );
if (FAILED(Status)) { goto end; }
//
// Call the "GetClusterConfiguration" method
//
{ HRESULT hr;
wprintf(L"Going get GetClusterConfiguration...\n");
hr = spWbemService->ExecMethod( _bstr_t(pRelPath), L"GetClusterConfiguration", 0, NULL, spWbemInput, &spWbemOutput, NULL ); if( FAILED( hr) ) { wprintf(L"GetClusterConfiguration returns with failure 0x%8lx\n", (UINT) hr); goto end; } else { wprintf(L"GetClusterConfiguration returns successfully\n"); }
if (spWbemOutput == NULL) { //
// Hmm --- no output ?!
//
printf("ExecMethod GetClusterConfiguration had no output"); Status = WBEM_E_NOT_FOUND; goto end; } }
//
// Extract params from the "GetClusterConfiguration" method
//
Status = extract_GetClusterConfiguration_output_params( spWbemOutput, pCurrentCfg );
end:
if (pRelPath != NULL) { delete pRelPath; }
spWbemService = NULL; // Smart pointer
spWbemInput = NULL; // smart pointer
spWbemOutput = NULL; // smart pointer.
return Status; }
WBEMSTATUS NlbHostDoUpdate( IN LPCWSTR szMachine, // NULL or empty for local
IN LPCWSTR szNicGuid, IN LPCWSTR szClientDescription, IN PNLB_EXTENDED_CLUSTER_CONFIGURATION pNewState, OUT UINT *pGeneration, OUT WCHAR **ppLog // free using delete operator.
) {
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; IWbemServicesPtr spWbemService = NULL; // Smart pointer
IWbemClassObjectPtr spWbemInput = NULL; // smart pointer
IWbemClassObjectPtr spWbemOutput = NULL; // smart pointer.
LPWSTR pRelPath = NULL;
*pGeneration = 0; *ppLog = NULL;
//
// Get interface to the NLB namespace on the specified machine
//
{ #define _MaxLen 256
WCHAR NetworkResource[_MaxLen];
if (*szMachine == 0) { szMachine = L"."; } _snwprintf(NetworkResource, (_MaxLen-1), L"\\\\%ws\\root\\microsoftnlb", szMachine); NetworkResource[_MaxLen-1]=0;
wprintf(L"Connecting to NLB on %ws ...\n", szMachine);
Status = CfgUtilConnectToServer( NetworkResource, NULL, // szUser
NULL, // szPassword
NULL, // szAuthority (domain)
&spWbemService ); if (FAILED(Status)) { wprintf(L"ERROR: COULD NOT CONNECT TO NLB ON %ws\n", szMachine); goto end; } wprintf(L"Successfully connected to NLB on %ws...\n", szMachine); }
//
// Get wmi input instance to "UpdateClusterConfiguration" method
//
{ Status = CfgUtilGetWmiInputInstanceAndRelPath( spWbemService, L"NlbsNic", // szClassName
L"AdapterGuid", // szParameterName
szNicGuid, // szPropertyValue
L"UpdateClusterConfiguration", // szMethodName,
spWbemInput, // smart pointer
&pRelPath // free using delete
);
if (FAILED(Status)) { wprintf( L"ERROR 0x%08lx trying to get instance of UpdateConfiguration\n", (UINT) Status ); goto end; } }
//
// Setup params for the "UpdateClusterConfiguration" method
// NOTE: spWbemInput could be NULL.
//
Status = setup_UpdateClusterConfiguration_input_params( szNicGuid, pNewState, spWbemInput );
if (FAILED(Status)) { goto end; }
//
// Call the "UpdateClusterConfiguration" method
//
{ HRESULT hr;
wprintf(L"Going get UpdateClusterConfiguration...\n");
hr = spWbemService->ExecMethod( _bstr_t(pRelPath), L"UpdateClusterConfiguration", 0, NULL, spWbemInput, &spWbemOutput, NULL ); if( FAILED( hr) ) { wprintf(L"UpdateConfiguration returns with failure 0x%8lx\n", (UINT) hr); goto end; } else { wprintf(L"UpdateConfiguration returns successfully\n"); }
if (spWbemOutput == NULL) { //
// Hmm --- no output ?!
//
printf("ExecMethod UpdateConfiguration had no output"); Status = WBEM_E_NOT_FOUND; goto end; } }
//
// Extract params from the "UpdateClusterConfiguration" method
//
{ DWORD dwReturnValue = 0;
Status = CfgUtilGetWmiDWORDParam( spWbemOutput, L"ReturnValue", // <--------------------------------
&dwReturnValue ); if (FAILED(Status)) { wprintf(L"Attempt to read ReturnValue failed. Error=0x%08lx\n", (UINT) Status); goto end; } LPWSTR szLog = NULL;
Status = CfgUtilGetWmiStringParam( spWbemOutput, L"Log", // <-------------------------
&szLog ); if (FAILED(Status)) { szLog = NULL; } *ppLog = szLog;
DWORD dwGeneration = 0; Status = CfgUtilGetWmiDWORDParam( spWbemOutput, L"NewGeneration", // <--------------------------------
&dwGeneration ); if (FAILED(Status)) { //
// Generation should always be specified for pending operations.
// TODO: for successful operations also?
//
if ((WBEMSTATUS)dwReturnValue == WBEM_S_PENDING) { wprintf(L"Attempt to read NewGeneration for pending update failed. Error=0x%08lx\n", (UINT) Status); Status = WBEM_E_CRITICAL_ERROR; goto end; } dwGeneration = 0; // we don't care if it's not set for non-pending
} *pGeneration = (UINT) dwGeneration;
//
// Make the return status reflect the true status of the update
// operation.
//
Status = (WBEMSTATUS) dwReturnValue; }
end:
if (pRelPath != NULL) { delete pRelPath; }
spWbemService = NULL; // Smart pointer
spWbemInput = NULL; // smart pointer
spWbemOutput = NULL; // smart pointer.
return Status; }
WBEMSTATUS NlbHostGetUpdateStatus( IN LPCWSTR szMachine, // NULL or empty for local
IN LPCWSTR szNicGuid, IN UINT Generation, OUT WBEMSTATUS *pCompletionStatus, OUT WCHAR **ppLog // free using delete operator.
) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; IWbemServicesPtr spWbemService = NULL; // Smart pointer
IWbemClassObjectPtr spWbemInput = NULL; // smart pointer
IWbemClassObjectPtr spWbemOutput = NULL; // smart pointer.
LPWSTR pRelPath = NULL;
*ppLog = NULL; *pCompletionStatus = WBEM_E_CRITICAL_ERROR;
//
// Get interface to the NLB namespace on the specified machine
//
{ #define _MaxLen 256
WCHAR NetworkResource[_MaxLen];
if (*szMachine == 0) { szMachine = L"."; } _snwprintf(NetworkResource, (_MaxLen-1), L"\\\\%ws\\root\\microsoftnlb", szMachine); NetworkResource[_MaxLen-1]=0;
// wprintf(L"Connecting to NLB on %ws ...\n", szMachine);
Status = CfgUtilConnectToServer( NetworkResource, NULL, // szUser
NULL, // szPassword
NULL, // szAuthority (domain)
&spWbemService ); if (FAILED(Status)) { wprintf(L"ERROR: COULD NOT CONNECT TO NLB ON %ws\n", szMachine); goto end; } // wprintf(L"Successfully connected to NLB on %ws...\n", szMachine);
}
//
// Get wmi input instance to "QueryConfigurationUpdateStatus" method
//
{ Status = CfgUtilGetWmiInputInstanceAndRelPath( spWbemService, L"NlbsNic", // szClassName
L"AdapterGuid", // szParameterName
szNicGuid, // szPropertyValue
L"QueryConfigurationUpdateStatus", // szMethodName,
spWbemInput, // smart pointer
&pRelPath // free using delete
);
if (FAILED(Status)) { wprintf( L"ERROR 0x%08lx trying to find instance to QueryUpdateStatus\n", (UINT) Status ); goto end; } }
//
// Setup params for the "QueryConfigurationUpdateStatus" method
// NOTE: spWbemInput could be NULL.
//
{ Status = CfgUtilSetWmiStringParam( spWbemInput, L"AdapterGuid", szNicGuid ); if (FAILED(Status)) { wprintf( L"Couldn't set Adapter GUID parameter to QueryUpdateStatus\n"); goto end; }
Status = CfgUtilSetWmiDWORDParam( spWbemInput, L"Generation", Generation ); if (FAILED(Status)) { wprintf( L"Couldn't set Generation parameter to QueryUpdateStatus\n"); goto end; } }
//
// Call the "QueryConfigurationUpdateStatus" method
//
{ HRESULT hr;
// wprintf(L"Going call QueryConfigurationUpdateStatus...\n");
hr = spWbemService->ExecMethod( _bstr_t(pRelPath), L"QueryConfigurationUpdateStatus", // szMethodName,
0, NULL, spWbemInput, &spWbemOutput, NULL ); if( FAILED( hr) ) { wprintf(L"QueryConfigurationUpdateStatus returns with failure 0x%8lx\n", (UINT) hr); goto end; } else { // wprintf(L"QueryConfigurationUpdateStatus returns successfully\n");
}
if (spWbemOutput == NULL) { //
// Hmm --- no output ?!
//
printf("ExecMethod QueryConfigurationUpdateStatus had no output"); Status = WBEM_E_NOT_FOUND; goto end; } }
//
// Extract output params --- return code and log.
//
{ DWORD dwReturnValue = 0;
Status = CfgUtilGetWmiDWORDParam( spWbemOutput, L"ReturnValue", // <--------------------------------
&dwReturnValue ); if (FAILED(Status)) { wprintf(L"Attempt to read ReturnValue failed. Error=0x%08lx\n", (UINT) Status); goto end; } *pCompletionStatus = (WBEMSTATUS) dwReturnValue; LPWSTR szLog = NULL;
Status = CfgUtilGetWmiStringParam( spWbemOutput, L"Log", // <-------------------------
&szLog ); if (FAILED(Status)) { szLog = NULL; } *ppLog = szLog;
ASSERT(Status != WBEM_S_PENDING); }
end:
if (pRelPath != NULL) { delete pRelPath; }
spWbemService = NULL; // Smart pointer
spWbemInput = NULL; // smart pointer
spWbemOutput = NULL; // smart pointer.
return Status; }
WBEMSTATUS setup_GetClusterConfiguration_input_params( IN LPCWSTR szNic, IN IWbemClassObjectPtr spWbemInput ) /*
Setup the input wmi parameters for the GetClusterConfiguration method */ { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
Status = CfgUtilSetWmiStringParam( spWbemInput, L"AdapterGuid", szNic ); return Status; }
WBEMSTATUS extract_GetClusterConfiguration_output_params( IN IWbemClassObjectPtr spWbemOutput, OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
DWORD Generation = 0; BOOL NlbBound = FALSE; LPWSTR *pszNetworkAddresses= NULL; UINT NumNetworkAddresses = 0; BOOL ValidNlbCfg = FALSE; LPWSTR szClusterName = NULL; LPWSTR szClusterNetworkAddress = NULL; LPWSTR szTrafficMode = NULL; NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE TrafficMode = NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST; LPWSTR *pszPortRules = NULL; UINT NumPortRules = 0; DWORD HostPriority = 0; LPWSTR szDedicatedNetworkAddress = NULL; NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE ClusterModeOnStart = NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STOPPED; BOOL RemoteControlEnabled= FALSE;
#if 0
[OUT] uint32 Generation, [OUT] String NetworkAddresses[], // "10.1.1.1/255.0.0.0"
[OUT] Boolean NLBBound, [OUT] String ClusterNetworkAddress, // "10.1.1.1/255.0.0.0"
[OUT] String ClusterName, [OUT] String TrafficMode, // UNICAST MULTICAST IGMPMULTICAST
[OUT] String PortRules[], [OUT] uint32 HostPriority, [OUT] String DedicatedNetworkAddress, // "10.1.1.1/255.0.0.0"
[OUT] Boolean ClusterModeOnStart, [OUT] Boolean RemoteControlEnabled #endif // 0
Status = CfgUtilGetWmiDWORDParam( spWbemOutput, L"Generation", // <--------------------------------
&Generation ); if (FAILED(Status)) { wprintf(L"Attempt to read Generation failed. Error=0x%08lx\n", (UINT) Status); goto end; }
Status = CfgUtilGetWmiStringArrayParam( spWbemOutput, L"NetworkAddresses", // <--------------------------------
&pszNetworkAddresses, &NumNetworkAddresses ); if (FAILED(Status)) { wprintf(L"Attempt to read Network addresses failed. Error=0x%08lx\n", (UINT) Status); goto end; }
Status = CfgUtilGetWmiBoolParam( spWbemOutput, L"NLBBound", // <--------------------------------
&NlbBound );
if (FAILED(Status)) { wprintf(L"Attempt to read NLBBound failed. Error=0x%08lx\n", (UINT) Status); goto end; }
do // while false -- just to allow us to break out
{ ValidNlbCfg = FALSE;
if (!NlbBound) { wprintf(L"NLB is UNBOUND\n"); break; } Status = CfgUtilGetWmiStringParam( spWbemOutput, L"ClusterNetworkAddress", // <-------------------------
&szClusterNetworkAddress ); if (FAILED(Status)) { wprintf(L"Attempt to read Cluster IP failed. Error=0x%08lx\n", (UINT) Status); break; } wprintf(L"NLB is BOUND, and the cluster address is %ws\n", szClusterNetworkAddress); Status = CfgUtilGetWmiStringParam( spWbemOutput, L"ClusterName", // <-------------------------
&szClusterName ); if (FAILED(Status)) { wprintf(L"Attempt to read Cluster Name failed. Error=0x%08lx\n", (UINT) Status); break; } //
// Traffic mode
//
{ Status = CfgUtilGetWmiStringParam( spWbemOutput, L"TrafficMode", // <-------------------------
&szTrafficMode ); if (FAILED(Status)) { wprintf(L"Attempt to read Traffic Mode failed. Error=0x%08lx\n", (UINT) Status); break; } if (!_wcsicmp(szTrafficMode, L"UNICAST")) { TrafficMode = NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST; } else if (!_wcsicmp(szTrafficMode, L"MULTICAST")) { TrafficMode = NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_MULTICAST; } else if (!_wcsicmp(szTrafficMode, L"IGMPMULTICAST")) { TrafficMode = NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_IGMPMULTICAST; } } // TODO: [OUT] String PortRules[],
Status = CfgUtilGetWmiDWORDParam( spWbemOutput, L"HostPriority", // <--------------------------------
&HostPriority ); if (FAILED(Status)) { wprintf(L"Attempt to read HostPriority failed. Error=0x%08lx\n", (UINT) Status); break; } Status = CfgUtilGetWmiStringParam( spWbemOutput, L"DedicatedNetworkAddress", // <-------------------------
&szDedicatedNetworkAddress ); if (FAILED(Status)) { wprintf(L"Attempt to read dedicated IP failed. Error=0x%08lx\n", (UINT) Status); break; } //
// StartMode
//
{ BOOL StartMode = FALSE; Status = CfgUtilGetWmiBoolParam( spWbemOutput, L"ClusterModeOnStart", // <-------------------------
&StartMode ); if (FAILED(Status)) { wprintf(L"Attempt to read ClusterModeOnStart failed. Error=0x%08lx\n", (UINT) Status); break; } if (StartMode) { ClusterModeOnStart = NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STARTED; } else { ClusterModeOnStart = NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STOPPED; } } Status = CfgUtilGetWmiBoolParam( spWbemOutput, L"RemoteControlEnabled", // <----------------------------
&RemoteControlEnabled ); if (FAILED(Status)) { wprintf(L"Attempt to read RemoteControlEnabled failed. Error=0x%08lx\n", (UINT) Status); break; }
ValidNlbCfg = TRUE;
} while (FALSE) ; //
// Now let's set all the the parameters in Cfg
//
{ pCfg->Generation = Generation; pCfg->fBound = NlbBound; Status = pCfg->SetNetworkAddresses( (LPCWSTR*) pszNetworkAddresses, NumNetworkAddresses ); if (FAILED(Status)) { wprintf(L"Attempt to set NetworkAddresses failed. Error=0x%08lx\n", (UINT) Status); goto end; } pCfg->fValidNlbCfg = ValidNlbCfg; pCfg->SetClusterName(szClusterName); pCfg->SetClusterNetworkAddress(szClusterNetworkAddress); pCfg->SetTrafficMode(TrafficMode); Status = pCfg->SetPortRules((LPCWSTR*)pszPortRules, NumPortRules); Status = WBEM_NO_ERROR; // TODO -- change once port rules is done
if (FAILED(Status)) { wprintf(L"Attempt to set PortRules failed. Error=0x%08lx\n", (UINT) Status); goto end; } pCfg->SetHostPriority(HostPriority); pCfg->SetDedicatedNetworkAddress(szDedicatedNetworkAddress); pCfg->SetClusterModeOnStart(ClusterModeOnStart); pCfg->SetRemoteControlEnabled(RemoteControlEnabled); } end:
delete szClusterNetworkAddress; delete pszNetworkAddresses; delete szClusterName; delete szTrafficMode; delete pszPortRules; delete szDedicatedNetworkAddress;
return Status; }
WBEMSTATUS setup_UpdateClusterConfiguration_input_params( IN LPCWSTR szNic, IN PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg, IN IWbemClassObjectPtr spWbemInput ) /*
Setup the input wmi parameters for the UpdateGetClusterConfiguration method
[IN] String ClientDescription, [IN] String AdapterGuid, [IN] uint32 Generation, [IN] Boolean PartialUpdate, [IN] String NetworkAddresses[], // "10.1.1.1/255.255.255.255"
[IN] Boolean NLBBound, [IN] String ClusterNetworkAddress, // "10.1.1.1/255.0.0.0"
[IN] String ClusterName, [IN] String TrafficMode, // UNICAST MULTICAST IGMPMULTICAST
[IN] String PortRules[], [IN] uint32 HostPriority, [IN] String DedicatedNetworkAddress, // "10.1.1.1/255.0.0.0"
[IN] Boolean ClusterModeOnStart, [IN] Boolean RemoteControlEnabled, [IN] String Password, */ { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
Status = CfgUtilSetWmiStringParam( spWbemInput, L"AdapterGuid", szNic ); //
// Fill in NetworkAddresses[]
//
{ LPWSTR *pszAddresses = NULL; UINT NumAddresses = 0; Status = pCfg->GetNetworkAddresses( &pszAddresses, &NumAddresses ); if (FAILED(Status)) { printf( "Setup update params: couldn't extract network addresses from Cfg" " for NIC %ws\n", szNic ); goto end; }
//
// Note it's ok to not specify any IP addresses -- in which case
// the default ip addresses will be set up.
//
if (pszAddresses != NULL) { Status = CfgUtilSetWmiStringArrayParam( spWbemInput, L"NetworkAddresses", (LPCWSTR *)pszAddresses, NumAddresses ); delete pszAddresses; pszAddresses = NULL; } }
if (!pCfg->IsNlbBound()) { //
// NLB is not bound
//
Status = CfgUtilSetWmiBoolParam(spWbemInput, L"NLBBound", FALSE); goto end; } else if (!pCfg->IsValidNlbConfig()) { printf( "Setup update params: NLB-specific configuration on NIC %ws is invalid\n", szNic ); Status = WBEM_E_INVALID_PARAMETER; goto end; }
Status = CfgUtilSetWmiBoolParam(spWbemInput, L"NLBBound", TRUE); if (FAILED(Status)) { printf("Error trying to set NLBBound parameter\n"); }
//
// NLB is bound
//
CfgUtilSetWmiBoolParam(spWbemInput, L"NLBBound", TRUE);
//
// Cluster name
//
{ LPWSTR szName = NULL; Status = pCfg->GetClusterName(&szName);
if (FAILED(Status)) { printf( "Setup update params: Could not extract cluster name for NIC %ws\n", szNic ); goto end; } CfgUtilSetWmiStringParam(spWbemInput, L"ClusterName", szName); delete (szName); szName = NULL; } //
// Cluster and dedicated network addresses
//
{ LPWSTR szAddress = NULL; Status = pCfg->GetClusterNetworkAddress(&szAddress);
if (FAILED(Status)) { printf( "Setup update params: Could not extract cluster address for NIC %ws\n", szNic ); goto end; } CfgUtilSetWmiStringParam( spWbemInput, L"ClusterNetworkAddress", szAddress ); delete (szAddress); szAddress = NULL;
Status = pCfg->GetDedicatedNetworkAddress(&szAddress);
if (FAILED(Status)) { printf( "Setup update params: Could not extract dedicated address for NIC %ws\n", szNic ); goto end; } CfgUtilSetWmiStringParam( spWbemInput, L"DedicatedNetworkAddress", szAddress ); delete (szAddress); szAddress = NULL; }
//
// TrafficMode
//
{ LPCWSTR szMode = NULL; switch(pCfg->GetTrafficMode()) { case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST: szMode = L"UNICAST"; break; case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_MULTICAST: szMode = L"MULTICAST"; break; case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_IGMPMULTICAST: szMode = L"IGMPMULTICAST"; break; default: assert(FALSE); Status = WBEM_E_CRITICAL_ERROR; goto end; } CfgUtilSetWmiStringParam(spWbemInput, L"TrafficMode", szMode); }
CfgUtilSetWmiDWORDParam( spWbemInput, L"HostPriority", pCfg->GetHostPriority() );
if (pCfg->GetClusterModeOnStart() == NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STARTED) { CfgUtilSetWmiBoolParam(spWbemInput, L"ClusterModeOnStart", TRUE); } else { CfgUtilSetWmiBoolParam(spWbemInput, L"ClusterModeOnStart", FALSE); }
CfgUtilSetWmiBoolParam( spWbemInput, L"RemoteControlEnabled", pCfg->GetRemoteControlEnabled() );
//
// TODO: get port rules
// [OUT] String PortRules[],
//
Status = WBEM_NO_ERROR;
end:
wprintf(L"<-Setup update params returns 0x%08lx\n", (UINT) Status);
return Status;
}
|