|
|
/******************************************************************
Copyright (c) 1999 Microsoft Corporation
NlbsNic.CPP -- WMI provider class implementation
Generated by Microsoft WMI Code Generation Engine TO DO: - See individual function headers - When linking, make sure you link to framedyd.lib & msvcrtd.lib (debug) or framedyn.lib & msvcrt.lib (retail).
Description: ******************************************************************/
// History:
// --------
//
// Revised by : mhakim
// Date : 02-12-01
// Reason : Added password support.
//
// Revised by : mhakim
// Date : 02-16-01
// Reason : Added friendly name support.
//
// Reason : filling out version info. This was being not
// done previously in GetObject.
#include <fwcommon.h> // This must be the first include.
#include "NlbsNic.h"
#include "NICCard.h"
#include "MNicInfo.h"
#include "MIPAddressAdmin.h"
#include "MNLBProviderSetting.h"
#include "Common.h"
#include "MUsingCom.h"
#include "WTokens.h"
#include "MNLBMachine.h"
#include <winbase.h> // For Sleep
#include <windows.h> // For Sleep
#include <string>
//#include <wlbsiocl.h>
#include "wlbsconfig.h"
#include "myntrtl.h"
#include "wlbsparm.h"
#include "cfgutils.h"
#include "updatecfg.h"
#include "nlbsnic.tmh"
using namespace std;
MUsingCom com;
BOOL g_UpdateConfigurationEnabled = FALSE;
WBEMSTATUS ProvGetClusterConfiguration( CInstance *pInParams, CInstance *pOutParams );
WBEMSTATUS ProvUpdateClusterConfiguration( CInstance *pInParams, CInstance *pOutParams );
WBEMSTATUS ProvQueryConfigurationUpdateStatus( CInstance *pInParams, CInstance *pOutParams );
WCHAR* CNlbsNic::version = L"03-09-2001";
// TO DO: Replace "NameSpace" with the appropriate namespace for your
// provider instance. For instance: "root\\default or "root\\cimv2".
// DONE : mhakim
//===================================================================
CNlbsNic MyNlbsNicSet (PROVIDER_NAME_NLBSNIC, L"root\\microsoftnlb") ;
// Property names
//===============
const static WCHAR* pAdapterGuid = L"AdapterGuid" ; const static WCHAR* pDependent = L"Dependent" ; const static WCHAR* pFriendlyName = L"FriendlyName" ; const static WCHAR* pFullName = L"FullName" ; const static WCHAR* pVersion = L"Version" ;
/*****************************************************************************
* * FUNCTION : CNlbsNic::CNlbsNic * * DESCRIPTION : Constructor * * INPUTS : none * * RETURNS : nothing * * COMMENTS : Calls the Provider constructor. * *****************************************************************************/ CNlbsNic::CNlbsNic (LPCWSTR lpwszName, LPCWSTR lpwszNameSpace ) : Provider(lpwszName, lpwszNameSpace) { //
// Enable WMI event tracing
//
WPP_INIT_TRACING(L"Microsoft\\NLB\\TPROV");
if (g_UpdateConfigurationEnabled) { //
// Initialize update config
//
NlbConfigurationUpdate::Initialize(); } }
/*****************************************************************************
* * FUNCTION : CNlbsNic::~CNlbsNic * * DESCRIPTION : Destructor * * INPUTS : none * * RETURNS : nothing * * COMMENTS : * *****************************************************************************/ CNlbsNic::~CNlbsNic () {
if (g_UpdateConfigurationEnabled) { //
// Deinitialize update config code
//
NlbConfigurationUpdate::Deinitialize(); }
//
// Disable WMI event tracing
//
WPP_CLEANUP(); }
/*****************************************************************************
* * FUNCTION : CNlbsNic::EnumerateInstances * * DESCRIPTION : Returns all the instances of this class. * * INPUTS : A pointer to the MethodContext for communication with WinMgmt. * A long that contains the flags described in * IWbemServices::CreateInstanceEnumAsync. Note that the following * flags are handled by (and filtered out by) WinMgmt: * WBEM_FLAG_DEEP * WBEM_FLAG_SHALLOW * WBEM_FLAG_RETURN_IMMEDIATELY * WBEM_FLAG_FORWARD_ONLY * WBEM_FLAG_BIDIRECTIONAL * * RETURNS : WBEM_S_NO_ERROR if successful * * COMMENTS : TO DO: All instances on the machine should be returned here and * all properties that this class knows how to populate must * be filled in. If there are no instances, return * WBEM_S_NO_ERROR. It is not an error to have no instances. * If you are implementing a 'method only' provider, you * should remove this method. * DONE: mhakim * *****************************************************************************/ HRESULT CNlbsNic::EnumerateInstances ( MethodContext* pMethodContext, long lFlags ) { HRESULT hRes = WBEM_S_NO_ERROR;
// get information about all nics on the machine.
//
NICCard::NICCard_Error errN; vector< NICCard::Info > nicList; errN = NICCard::getNics( &nicList ); if( errN != NICCard::NICCard_SUCCESS ) { return WBEM_E_NOT_FOUND; }
// populate all instances.
//
for( int i = 0; i < nicList.size(); ++i ) { CInstance* pInstance = CreateNewInstance(pMethodContext);
pInstance->SetCHString(pAdapterGuid, nicList[i].guid.c_str() );
pInstance->SetCHString(pFriendlyName, nicList[i].friendlyName.c_str() );
pInstance->SetCHString(pFullName, nicList[i].fullName.c_str() );
pInstance->SetCHString(pVersion, version );
hRes = pInstance->Commit(); pInstance->Release(); } hRes = WBEM_S_NO_ERROR; return hRes ; }
/*****************************************************************************
* * FUNCTION : CNlbsNic::GetObject * * DESCRIPTION : Find a single instance based on the key properties for the * class. * * INPUTS : A pointer to a CInstance object containing the key properties. * A long that contains the flags described in * IWbemServices::GetObjectAsync. * * RETURNS : WBEM_S_NO_ERROR if the instance can be found * WBEM_E_NOT_FOUND if the instance described by the key properties * could not be found * WBEM_E_FAILED if the instance could be found but another error * occurred. * * COMMENTS : If you are implementing a 'method only' provider, you should * remove this method. * *****************************************************************************/ HRESULT CNlbsNic::GetObject ( CInstance* pInstance, long lFlags ) { HRESULT hr = WBEM_E_NOT_FOUND;
CHString sTemp; pInstance->GetCHString( L"FullName", sTemp ); wstring fullName = sTemp;
NICCard::NICCard_Error errN; vector< NICCard::Info > nicList; errN = NICCard::getNics( &nicList ); if( errN != NICCard::NICCard_SUCCESS ) { return WBEM_E_NOT_FOUND; }
// populate all instances.
//
hr = WBEM_E_NOT_FOUND; for( int i = 0; i < nicList.size(); ++i ) { if( nicList[i].fullName == fullName ) { // found specific instance.
//
pInstance->SetCHString(pAdapterGuid, nicList[i].guid.c_str() );
pInstance->SetCHString(pFriendlyName, nicList[i].friendlyName.c_str() );
pInstance->SetCHString(pFullName, nicList[i].fullName.c_str() );
pInstance->SetCHString(pVersion, version );
hr = WBEM_S_NO_ERROR; break; } }
return hr; }
/*****************************************************************************
* * FUNCTION : CNlbsNic::ExecQuery * * DESCRIPTION : You are passed a method context to use in the creation of * instances that satisfy the query, and a CFrameworkQuery * which describes the query. Create and populate all * instances which satisfy the query. You may return more * instances or more properties than are requested and WinMgmt * will post filter out any that do not apply. * * INPUTS : A pointer to the MethodContext for communication with WinMgmt. * A query object describing the query to satisfy. * A long that contains the flags described in * IWbemServices::CreateInstanceEnumAsync. Note that the following * flags are handled by (and filtered out by) WinMgmt: * WBEM_FLAG_FORWARD_ONLY * WBEM_FLAG_BIDIRECTIONAL * WBEM_FLAG_ENSURE_LOCATABLE * * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if queries not supported for * this class or if the query is too complex for this class * to interpret. The framework will call the EnumerateInstances * function instead and let Winmgmt post filter. * WBEM_E_FAILED if the query failed * WBEM_S_NO_ERROR if query was successful * * COMMENTS : TO DO: Most providers will not need to implement this method. If you don't, WinMgmt * will call your enumerate function to get all the instances and perform the * filtering for you. Unless you expect SIGNIFICANT savings from implementing * queries, you should remove this method. You should also remove this method * if you are implementing a 'method only' provider. * *****************************************************************************/ HRESULT CNlbsNic::ExecQuery (MethodContext *pMethodContext, CFrameworkQuery& Query, long lFlags) { return (WBEM_E_PROVIDER_NOT_CAPABLE); }
/*****************************************************************************
* * FUNCTION : CNlbsNic::PutInstance * * DESCRIPTION : PutInstance should be used in provider classes that can * write instance information back to the hardware or * software. For example: Win32_Environment will allow a * PutInstance to create or update an environment variable. * However, a class like MotherboardDevice will not allow * editing of the number of slots, since it is difficult for * a provider to affect that number. * * INPUTS : A pointer to a CInstance object containing the key properties. * A long that contains the flags described in * IWbemServices::PutInstanceAsync. * * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if PutInstance is not available * WBEM_E_FAILED if there is an error delivering the instance * WBEM_E_INVALID_PARAMETER if any of the instance properties * are incorrect. * WBEM_S_NO_ERROR if instance is properly delivered * * COMMENTS : TO DO: If you don't intend to support writing to your provider, * or are creating a 'method only' provider, remove this * method. * *****************************************************************************/ HRESULT CNlbsNic::PutInstance ( const CInstance &Instance, long lFlags) { // Use the CInstance Get functions (for example, call
// GetCHString(L"Name", sTemp)) against Instance to see the key values
// the client requested.
return (WBEM_E_PROVIDER_NOT_CAPABLE); }
/*****************************************************************************
* * FUNCTION : CNlbsNic::DeleteInstance * * DESCRIPTION : DeleteInstance, like PutInstance, actually writes information * to the software or hardware. For most hardware devices, * DeleteInstance should not be implemented, but for software * configuration, DeleteInstance implementation is plausible. * * INPUTS : A pointer to a CInstance object containing the key properties. * A long that contains the flags described in * IWbemServices::DeleteInstanceAsync. * * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if DeleteInstance is not available. * WBEM_E_FAILED if there is an error deleting the instance. * WBEM_E_INVALID_PARAMETER if any of the instance properties * are incorrect. * WBEM_S_NO_ERROR if instance is properly deleted. * * COMMENTS : TO DO: If you don't intend to support deleting instances or are * creating a 'method only' provider, remove this method. * *****************************************************************************/ HRESULT CNlbsNic::DeleteInstance ( const CInstance &Instance, long lFlags ) { // Use the CInstance Get functions (for example, call
// GetCHString(L"Name", sTemp)) against Instance to see the key values
// the client requested.
return (WBEM_E_PROVIDER_NOT_CAPABLE); }
/*****************************************************************************
* * FUNCTION : CNlbsNic::ExecMethod * * DESCRIPTION : Override this function to provide support for methods. * A method is an entry point for the user of your provider * to request your class perform some function above and * beyond a change of state. (A change of state should be * handled by PutInstance() ) * * INPUTS : A pointer to a CInstance containing the instance the method was executed against. * A string containing the method name * A pointer to the CInstance which contains the IN parameters. * A pointer to the CInstance to contain the OUT parameters. * A set of specialized method flags * * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if not implemented for this class * WBEM_S_NO_ERROR if method executes successfully * WBEM_E_FAILED if error occurs executing method * * COMMENTS : TO DO: If you don't intend to support Methods, remove this method. * *****************************************************************************/ HRESULT CNlbsNic::ExecMethod ( const CInstance& Instance, const BSTR bstrMethodName, CInstance *pInParams, CInstance *pOutParams, long lFlags) { // For non-static methods, use the CInstance Get functions (for example,
// call GetCHString(L"Name", sTemp)) against Instance to see the key
// values the client requested.
HRESULT hresult = WBEM_E_PROVIDER_NOT_CAPABLE;
CHString sTemp;
wstring fullName;
wstring clusterIPAddress; wstring clusterNetworkMask; wstring clusterName; wstring password;
_variant_t hostPriority; wstring dedicatedIPAddress; wstring dedicatedNetworkMask;
bool retBool;
Instance.GetCHString( L"FullName", sTemp ); fullName = sTemp;
NICCard nic( NICCard::fullName, fullName );
NICCard::NICCard_Error err;
DWORD retValue= 100;
if (_wcsicmp(bstrMethodName, L"IsBound") == 0) { // check if bound or not.
err = nic.isBoundTo( L"ms_wlbs");
if( err == NICCard::BOUND ) { retValue = 1; } else if( err == NICCard::UNBOUND ) { retValue = 0; } else if( err == NICCard::NO_SUCH_NIC ) { retValue = 20; } else if( err == NICCard::NO_SUCH_COMPONENT ) { retValue = 30; } else { retValue = 40; }
hresult = WBEM_S_NO_ERROR; pOutParams->SetDWORD(L"ReturnValue", retValue); return hresult;
} else if (_wcsicmp(bstrMethodName, L"Bind") == 0) { // bind nlbs to the nic.
err = nic.bind( L"ms_wlbs" ); if( err == NICCard::NICCard_SUCCESS ) { retValue = 0; } else if( err == NICCard::NO_SUCH_NIC ) { retValue = 20; } else if( err == NICCard::NO_SUCH_COMPONENT ) { retValue = 30; } else { retValue = 40; }
hresult = WBEM_S_NO_ERROR; pOutParams->SetDWORD(L"ReturnValue", retValue); return hresult;
} else if (_wcsicmp(bstrMethodName, L"Unbind") == 0) { // unbind nlbs from nic
err = nic.unbind( L"ms_wlbs" );
if( err == NICCard::NICCard_SUCCESS ) { retValue = 0; } else if( err == NICCard::NO_SUCH_NIC ) { retValue = 20; } else if( err == NICCard::NO_SUCH_COMPONENT ) { retValue = 30; } else { retValue = 40; }
hresult = WBEM_S_NO_ERROR; pOutParams->SetDWORD(L"ReturnValue", retValue); return hresult;
} else if (_wcsicmp(bstrMethodName, L"BindAndConfigure") == 0) { // here we need to be passed everything
// required to configure cluster completely
// on this machine.
// bind nlbs to the nic.
err = nic.bind( L"ms_wlbs" );
if( err == NICCard::NICCard_SUCCESS ) { MNLBProviderSetting nlbs( fullName.c_str() );
// remove all old port rules.
// removing LB port rules
vector<MNLBPortRuleLoadBalanced> portLB; nlbs.getPortRulesLoadBalanced( &portLB ); for( int i = 0; i < portLB.size(); ++i ) { nlbs.removePortRuleLoadBalanced( portLB[i] ); }
// removing D port rules
vector<MNLBPortRuleDisabled> portD; nlbs.getPortRulesDisabled( &portD ); for( int i = 0; i < portD.size(); ++i ) { nlbs.removePortRuleDisabled( portD[i] ); } // removing Failover port rules
vector<MNLBPortRuleFailover> portF; nlbs.getPortRulesFailover( &portF );
for( int i = 0; i < portF.size(); ++i ) { nlbs.removePortRuleFailover( portF[i] ); }
//
// get port rules to configure.
//
SAFEARRAY* portRulesArray; SAFEARRAYBOUND sb; sb.lLbound = 0; sb.cElements = 100;
portRulesArray = SafeArrayCreate( VT_BSTR, 1, &sb );
pInParams->GetStringArray( L"PortRules", portRulesArray );
vector<_bstr_t> portRulesVector; GetVectorFromSafeArray( portRulesArray, portRulesVector );
ClusterData clusterData; FillInPortRules( &clusterData, L"rashuma", portRulesVector );
// add all new port rules.
// equal load balanced.
map< long, PortDataELB>::iterator topELB;
for( topELB = clusterData.portELB.begin(); topELB != clusterData.portELB.end(); ++topELB ) { nlbs.addPortRuleLoadBalanced( (*topELB).second ); }
// unequal load balanced
map< long, PortDataULB>::iterator topULB; for( topULB = clusterData.portULB.begin(); topULB != clusterData.portULB.end(); ++topULB ) { MNLBPortRuleLoadBalanced portRuleULB = (*topULB).second; portRuleULB._load = (*topULB).second.machineMapToLoadWeight[L"rashuma"]; nlbs.addPortRuleLoadBalanced( portRuleULB ); }
// disabled
map< long, PortDataD>::iterator topD; for( topD = clusterData.portD.begin(); topD != clusterData.portD.end(); ++topD ) { nlbs.addPortRuleDisabled( (*topD).second ); }
// failover
map< long, PortDataF>::iterator topF; for( topF = clusterData.portF.begin(); topF != clusterData.portF.end(); ++topF ) { MNLBPortRuleFailover portRuleF = (*topF).second; portRuleF._priority = (*topF).second.machineMapToPriority[ L"rashuma" ]; nlbs.addPortRuleFailover( portRuleF ); }
//
// set host properties.
//
HostProperties hp;
// host priority
pInParams->GetVariant( L"HostPriority", hostPriority ); hp.hID = hostPriority;
// dip
pInParams->GetCHString( L"DedicatedIPAddress", sTemp ); dedicatedIPAddress = sTemp; hp.hIP = dedicatedIPAddress.c_str();
// dsn
pInParams->GetCHString( L"DedicatedNetworkMask", sTemp ); dedicatedNetworkMask = sTemp; hp.hSubnetMask = dedicatedNetworkMask.c_str();
// initial state ?
pInParams->Getbool( L"ClusterModeOnStart", hp.initialClusterStateActive );
unsigned long retVal; nlbs.setHostProperties( hp, &retVal );
//
// set cluster properties.
//
ClusterProperties cp; RetreiveAndSetClusterProperties(pInParams, nlbs, cp, fullName );
//
// if initial state active start cluster
// else stop cluster.
//
MNLBMachine nlbMachine( cp.cIP );
if( hp.initialClusterStateActive == true ) { nlbMachine.start( Common::THIS_HOST, &retVal ); } else { nlbMachine.stop( Common::THIS_HOST, &retVal ); }
retValue = 0; } else if( err == NICCard::NO_SUCH_NIC ) { retValue = 20; } else if( err == NICCard::NO_SUCH_COMPONENT ) { retValue = 30; } else { retValue = 40; }
hresult = WBEM_S_NO_ERROR; pOutParams->SetDWORD(L"ReturnValue", retValue); return hresult;
} else if (_wcsicmp(bstrMethodName, L"ModifyClusterProperties") == 0) { // check if nic is bound to adapter or not.
err = nic.isBoundTo( L"ms_wlbs" ); if( err == NICCard::BOUND ) { MNLBProviderSetting nlbs( fullName.c_str() ); //
// set cluster properties.
//
ClusterProperties cp; RetreiveAndSetClusterProperties(pInParams, nlbs, cp, fullName);
} else if( err == NICCard::UNBOUND ) { retValue = 10; } else if( err == NICCard::NO_SUCH_NIC ) { retValue = 20; } else if( err == NICCard::NO_SUCH_COMPONENT ) { retValue = 30; } else { retValue = 40; }
hresult = WBEM_S_NO_ERROR; pOutParams->SetDWORD(L"ReturnValue", retValue); return hresult; } else if (_wcsicmp(bstrMethodName, L"GetClusterConfiguration") == 0) { hresult = ProvGetClusterConfiguration( pInParams, pOutParams ); return hresult; } else if (_wcsicmp(bstrMethodName, L"UpdateClusterConfiguration") == 0) { hresult = ProvUpdateClusterConfiguration( pInParams, pOutParams ); return hresult; } else if (_wcsicmp(bstrMethodName, L"QueryConfigurationUpdateStatus") == 0) { hresult = ProvQueryConfigurationUpdateStatus( pInParams, pOutParams ); return hresult; } else { // unknown call, we do not support this.
hresult = WBEM_E_PROVIDER_NOT_CAPABLE; pOutParams->SetDWORD(L"ReturnValue", retValue); return hresult; } }
void CNlbsNic::RetreiveAndSetClusterProperties(CInstance *pInParams, MNLBProviderSetting &nlbs, ClusterProperties& cp, const wstring& fullName ) { CHString sTemp; wstring clusterIPAddress; wstring clusterNetworkMask; wstring clusterName; wstring password;
// cip
pInParams->GetCHString( L"ClusterIPAddress", sTemp ); clusterIPAddress = sTemp; cp.cIP = clusterIPAddress.c_str();
// csn
pInParams->GetCHString( L"ClusterNetworkMask", sTemp ); clusterNetworkMask = sTemp; cp.cSubnetMask = clusterNetworkMask.c_str();
// full internet name
pInParams->GetCHString( L"ClusterName", sTemp ); clusterName = sTemp; cp.cFullInternetName = clusterName.c_str();
// igmp support?
pInParams->Getbool( L"IGMPSupport", cp.igmpSupportEnabled );
// multicast enabled?
pInParams->Getbool( L"MulticastSupportEnabled", cp.multicastSupportEnabled );
// remote control enabled?
pInParams->Getbool( L"RemoteControlEnabled", cp.remoteControlEnabled );
// password
pInParams->GetCHString( L"Password", sTemp ); password = sTemp; cp.password = password.c_str();
unsigned long retVal; try { nlbs.setClusterProperties( cp, &retVal ); } catch( _com_error e ) { }
// set password.
try { if( cp.remoteControlEnabled == true ) { nlbs.setPassword( cp.password, &retVal ); } } catch( _com_error e ) { } //
// add cluster ip
//
MIPAddressAdmin ipAdmin( fullName.c_str() ); long SleepDuration = 0; while ((ipAdmin.addIPAddress(cp.cIP, cp.cSubnetMask) != MIPAddressAdmin::MIPAddressAdmin_SUCCESS) &&(SleepDuration < PROTOCOL_BIND_DELAY)) { SleepDuration += PROTOCOL_BIND_WAIT_INCREMENT; Sleep(PROTOCOL_BIND_WAIT_INCREMENT); } }
void CNlbsNic::GetVectorFromSafeArray( SAFEARRAY*& stringArray, vector<_bstr_t>& strings ) { LONG count = stringArray->rgsabound[0].cElements; BSTR* pbstr; HRESULT hr;
if( SUCCEEDED( SafeArrayAccessData( stringArray, ( void **) &pbstr))) { for( LONG x = 0; x < count; x++ ) { strings.push_back( pbstr[x] ); }
hr = SafeArrayUnaccessData( stringArray ); } }
void CNlbsNic::FillInPortRules( ClusterData* p_clusterData, const _bstr_t& myMachine, const vector<_bstr_t>& portRules ) { wchar_t portBuf[1000]; wstring temp; WTokens tok; vector<wstring> tokens;
for( int i = 0; i < portRules.size(); ++i ) { wcscpy( portBuf, portRules[i] );
tok.init( portBuf, L"\t"); tokens = tok.tokenize();
if( tokens[3] == L"Multiple" ) { if( tokens[5] == L"Equal" ) { p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._startPort = _wtoi( tokens[0].c_str() ); p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._endPort = _wtoi( tokens[1].c_str() ); if( tokens[2] == L"Both" ) { p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::both; } else if( tokens[2] == L"TCP" ) { p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::tcp; } else { p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::udp; } if( tokens[6] == L"Single" ) { p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._affinity = MNLBPortRule::single; } else if( tokens[6] == L"None" ) { p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._affinity = MNLBPortRule::none; } else { p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._affinity = MNLBPortRule::classC; }
p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._isEqualLoadBalanced = true; } else { p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._startPort = _wtoi( tokens[0].c_str() ); p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._endPort = _wtoi( tokens[1].c_str() ); if( tokens[2] == L"Both" ) { p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::both; } else if( tokens[2] == L"TCP" ) { p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::tcp; } else { p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::udp; } if( tokens[6] == L"Single" ) { p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._affinity = MNLBPortRule::single; } else if( tokens[6] == L"None" ) { p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._affinity = MNLBPortRule::none; } else { p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._affinity = MNLBPortRule::classC; }
p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._isEqualLoadBalanced = false;
p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ].machineMapToLoadWeight[myMachine] = _wtoi( tokens[5].c_str() ); } } else if ( tokens[3] == L"Single" ) { p_clusterData->portF[ _wtoi( tokens[0].c_str()) ]._startPort = _wtoi( tokens[0].c_str() ); p_clusterData->portF[ _wtoi( tokens[0].c_str()) ]._endPort = _wtoi( tokens[1].c_str() ); if( tokens[2] == L"Both" ) { p_clusterData->portF[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::both; } else if( tokens[2] == L"TCP" ) { p_clusterData->portF[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::tcp; } else { p_clusterData->portF[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::udp; } p_clusterData->portF[ _wtoi( tokens[0].c_str()) ].machineMapToPriority[myMachine] = _wtoi( tokens[4].c_str() ); } else { p_clusterData->portD[ _wtoi( tokens[0].c_str()) ]._startPort = _wtoi( tokens[0].c_str() ); p_clusterData->portD[ _wtoi( tokens[0].c_str()) ]._endPort = _wtoi( tokens[1].c_str() ); if( tokens[2] == L"Both" ) { p_clusterData->portD[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::both; } else if( tokens[2] == L"TCP" ) { p_clusterData->portD[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::tcp; } else { p_clusterData->portD[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::udp; } } } }
WBEMSTATUS ProvGetClusterConfiguration( CInstance *pInParams, CInstance *pOutParams ) /*++
WMI provider wrapper around NlbConfigurationUpdate::GetConfiguration
--*/ { if (!g_UpdateConfigurationEnabled) return WBEM_E_PROVIDER_NOT_CAPABLE;
LPCWSTR pAdapterGuid = NULL; WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE; CHString sTemp; bool fRet; NLB_EXTENDED_CLUSTER_CONFIGURATION Cfg; SAFEARRAY *pSA = NULL;
/*
[IN] String AdapterGuid, [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 */
fRet = pInParams->GetCHString( L"AdapterGuid", sTemp ); if (!fRet) { TRACE_CRIT("->%!FUNC!: Missing adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; }
//
// Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
// buffer -- see operator LPCWSTR() of WString docs.
//
pAdapterGuid = (LPCWSTR) sTemp;
if (pAdapterGuid == NULL || *pAdapterGuid == 0) { TRACE_CRIT("->%!FUNC!: Null of empty adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; } else { TRACE_VERB(L"->%!FUNC!(Nic=%ws)", pAdapterGuid); }
Status = NlbConfigurationUpdate::GetConfiguration( pAdapterGuid, &Cfg );
if (FAILED(Status)) { goto end; }
pOutParams->SetDWORD(L"ReturnValue", (DWORD) WBEM_NO_ERROR); pOutParams->SetDWORD(L"Generation", Cfg.GetGeneration());
//
// Fill in NetworkAddresses[]
//
{ Status = Cfg.GetNetworkAddressesSafeArray( &pSA ); if (FAILED(Status)) { TRACE_CRIT( "%!FUNC!: couldn't extract network addresses from Cfg" " for NIC %ws", pAdapterGuid ); goto end; }
if (pSA!=NULL) { pOutParams->SetStringArray( L"NetworkAddresses", *pSA // pass by reference
); SafeArrayDestroy(pSA); pSA = NULL; } }
if (!Cfg.IsNlbBound()) { //
// NLB is bound
//
pOutParams->Setbool(L"NLBBound", FALSE); Status = WBEM_NO_ERROR; goto end; } //
// NLB is bound
//
pOutParams->Setbool(L"NLBBound", TRUE);
if (!Cfg.IsValidNlbConfig()) { TRACE_CRIT( "%!FUNC!: NLB-specific configuration on NIC %ws is invalid", pAdapterGuid ); goto end; }
//
// Cluster name
//
{ LPWSTR szName = NULL; Status = Cfg.GetClusterName(&szName);
if (FAILED(Status)) { TRACE_CRIT( "%!FUNC!: Could not extract cluster name for NIC %ws", pAdapterGuid ); goto end; } pOutParams->SetCHString(L"ClusterName", szName); delete (szName); szName = NULL; } //
// Cluster and dedicated network addresses
//
{ LPWSTR szAddress = NULL; Status = Cfg.GetClusterNetworkAddress(&szAddress);
if (FAILED(Status)) { TRACE_CRIT( "%!FUNC!: Could not extract cluster address for NIC %ws", pAdapterGuid ); goto end; } pOutParams->SetCHString(L"ClusterNetworkAddress", szAddress); delete (szAddress); szAddress = NULL;
Status = Cfg.GetDedicatedNetworkAddress(&szAddress);
if (FAILED(Status)) { TRACE_CRIT( "%!FUNC!: Could not extract dedicated address for NIC %ws", pAdapterGuid ); goto end; } pOutParams->SetCHString(L"DedicatedNetworkAddress", szAddress); delete (szAddress); szAddress = NULL; }
//
// TrafficMode
//
{ LPCWSTR szMode = NULL; switch(Cfg.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; } pOutParams->SetCHString(L"TrafficMode", szMode); }
pOutParams->SetDWORD(L"HostPriority", Cfg.GetHostPriority());
if (Cfg.GetClusterModeOnStart() == NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STARTED) { pOutParams->Setbool(L"ClusterModeOnStart", TRUE); } else { pOutParams->Setbool(L"ClusterModeOnStart", FALSE); }
pOutParams->Setbool(L"RemoteControlEnabled", Cfg.GetRemoteControlEnabled());
//
// TODO: get port rules
// [OUT] String PortRules[],
//
Status = WBEM_NO_ERROR;
end:
if (pSA!=NULL) { SafeArrayDestroy(pSA); pSA = NULL; }
TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
return Status;
}
WBEMSTATUS ProvUpdateClusterConfiguration( CInstance *pInParams, CInstance *pOutParams ) /*++
WMI provider wrapper NlbConfigurationUpdate::UpdateConfiguration with some additional wrinkles: we selectively update the current version.
--*/ { if (!g_UpdateConfigurationEnabled) return WBEM_E_PROVIDER_NOT_CAPABLE;
LPCWSTR pAdapterGuid = NULL; LPCWSTR pClientDescription = L"Unspecified WMI Client"; // TODO: localize
WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE; CHString sClientDescription; CHString sAdapterGuid; CHString sTemp; bool fRet; NLB_EXTENDED_CLUSTER_CONFIGURATION Cfg; SAFEARRAY *pSA = NULL;
/*
[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, [OUT] uint32 NewGeneration, [OUT] String Log */
fRet = pInParams->GetCHString( L"ClientDescription", sClientDescription); if (fRet) { // Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
pClientDescription = (LPCWSTR) sClientDescription; }
fRet = pInParams->GetCHString( L"AdapterGuid", sAdapterGuid); if (!fRet) { TRACE_CRIT("->%!FUNC!: Missing adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; }
//
// Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
// buffer -- see operator LPCWSTR() of WString docs.
//
pAdapterGuid = (LPCWSTR) sAdapterGuid;
if (pAdapterGuid == NULL || *pAdapterGuid == 0) { TRACE_CRIT("->%!FUNC!: Null of empty adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; } else { TRACE_VERB(L"->%!FUNC!(Nic=%ws)", pAdapterGuid); }
//
// Get the current configuration
//
Status = NlbConfigurationUpdate::GetConfiguration( pAdapterGuid, &Cfg );
if (FAILED(Status)) { goto end; }
//
// Modify the snapshot of the current configuration with whatever
// cluster configuration information is specified in the input
// parameters
//
{ DWORD InGeneration = 0; bool NlbBound = FALSE; bool bResult = FALSE; bool bPartialUpdate = FALSE; //
// Determine if this is a partial or full update.
// If partial update, we allow a subset of cluster configuration
// parameters to be specified, but allow only a restricted set
// of update operations.
//
// Disallowed partial update operations:
// - Transitions between bound and !bound
// - Currently bound but nlb parameters are invalid
//
// Some allowed partial updates:
// - Modifying IP address lists
// - Modifying cluster / dedicated addresses/subnets
// - Modifying existing portrules
// - Adding/deleting port rules
//
bResult = pInParams->GetDWORD( L"Generation", // <--------------------------------
InGeneration ); if (!bResult) { //
// We allow generation to be unspecified.
//
InGeneration = 0; } else { //
// If generation is specified,
// we verify that the current generation matches the
// specified generation.
// TODO: this really must be done in the context of
// mfn_Start update -- after we've acquired the global lock!
//
if (InGeneration != Cfg.GetGeneration()) { TRACE_CRIT("Partial update: input generation(%lu) != current generation(%lu)", InGeneration, Cfg.GetGeneration()); Status = WBEM_E_HANDLE_OUT_OF_DATE; goto end; } }
bResult = pInParams->Getbool( L"NLBBound", // <--------------------------------
NlbBound ); if (!bResult) { NlbBound = Cfg.IsNlbBound(); TRACE_CRIT(L"Could not read NLBBound -- assuming current state %d.", NlbBound); }
bResult = pInParams->GetStringArray( L"NetworkAddresses", // <--------------------------------
pSA ); if (!bResult) { //
// We set pCfg to zero addresses, which causes update to
// use it's own defaults...
//
TRACE_CRIT(L"Could not read Network addresses -- using defaults"); Status = Cfg.SetNetworkAddresses(NULL, 0); pSA = NULL; } else { if (pSA != NULL) { Status = Cfg.SetNetworkAddressesSafeArray(pSA); SafeArrayDestroy(pSA); pSA = NULL; } }
if (!NlbBound) { // NLB is not to be bound -- no need to read the input params.
Cfg.fBound = FALSE; Cfg.fValidNlbCfg = FALSE; } else { BOOL fNewConfig = FALSE;
if (!Cfg.fBound || Cfg.fValidNlbCfg == FALSE) { //
// If we were previously unbound or we were bound but with
// a bad configuration, we need to setup our
// new cfg with good defaults
//
CfgUtilInitializeParams(&Cfg.NlbParams); Cfg.fBound = TRUE; Cfg.fValidNlbCfg = TRUE; fNewConfig = TRUE; } bResult = pInParams->GetCHString( L"ClusterNetworkAddress", // <--------------------
sTemp ); if (!bResult) { if (fNewConfig) { //
// Cluster address MUST be specified for new config.
//
TRACE_CRIT(L"ERROR: Could not read Cluster IP for new config."); Status = WBEM_E_INVALID_PARAMETER; goto end; } TRACE_CRIT(L"Could not read Cluster IP. Keeping existing."); } else { LPCWSTR szClusterNetworkAddress = NULL; szClusterNetworkAddress = (LPCWSTR) sTemp; // no copies here.
Cfg.SetClusterNetworkAddress(szClusterNetworkAddress); szClusterNetworkAddress = NULL; } bResult = pInParams->GetCHString( L"ClusterName", // <-------------------------
sTemp ); if (!bResult) { TRACE_CRIT(L"Could not read Cluster Name. Keeping existing"); } else { LPCWSTR szClusterName = NULL; szClusterName = (LPCWSTR) sTemp; // no copies here.
Cfg.SetClusterName(szClusterName); szClusterName = NULL; } //
// Traffic mode
//
{ bResult = pInParams->GetCHString( L"TrafficMode", // <-------------------------
sTemp ); if (!bResult) { TRACE_CRIT(L"Could not read TrafficMode. Keeping existing"); } else { LPCWSTR szTrafficMode = NULL; NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE TrafficMode = NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST; szTrafficMode = (LPCWSTR) sTemp; // no copies here.
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; } else { TRACE_CRIT("Invalid TrafficMode: %ws", szTrafficMode); Status = WBEM_E_INVALID_PARAMETER; goto end; }
Cfg.SetTrafficMode(TrafficMode); szTrafficMode = NULL; } } //
// TODO: process port rules.
// [OUT] String PortRules[]
//
DWORD HostPriority = 0; bResult = pInParams->GetDWORD( L"HostPriority", // <---------------------------
HostPriority ); if (!bResult) { TRACE_CRIT(L"Could not read HostPriority. Keeping existing"); } else { Cfg.SetHostPriority(HostPriority); } bResult = pInParams->GetCHString( L"DedicatedNetworkAddress", // <-----------------
sTemp ); if (!bResult) { TRACE_CRIT(L"Could not dedicated IP. Keeping existing"); } else { LPCWSTR szAddress = NULL; szAddress = (LPCWSTR) sTemp; // no copies here.
Cfg.SetDedicatedNetworkAddress(szAddress);
//
// For now, we'll always try to add the dedicated IP address
// to the NIC.
//
Cfg.fAddDedicatedIp = TRUE; szAddress = NULL; } //
// StartMode
//
{ bool StartMode = FALSE; bResult = pInParams->Getbool( L"ClusterModeOnStart", // <-----------------
StartMode ); if (!bResult) { TRACE_CRIT(L"Could not read StartMode. Keeping existing"); } else { NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE ClusterModeOnStart; if (StartMode) { ClusterModeOnStart = NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STARTED; } else { ClusterModeOnStart = NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STOPPED; } Cfg.SetClusterModeOnStart(ClusterModeOnStart); } } //
// Remote control enabled
//
{ bool bRemoteControlEnabled; bResult = pInParams->Getbool( L"RemoteControlEnabled", // <---------------
bRemoteControlEnabled ); if (!bResult) { TRACE_CRIT(L"Could not read RemoteControlEnabled. Keeping existing"); } else { Cfg.SetRemoteControlEnabled(bRemoteControlEnabled!=FALSE); } }
//
// TODO: if PartialUpdate is specified, we need to
// make sure that fValidNlbCfg is already set.
//
Cfg.fValidNlbCfg = TRUE; } while (FALSE) ;
}
//
// Call NlbConfigurationUpdate::DuUpdate to do the actual work.
//
UINT NewGeneration = 0; LPWSTR pLog = NULL;
Status = NlbConfigurationUpdate::DoUpdate( pAdapterGuid, pClientDescription, &Cfg, &NewGeneration, &pLog );
//
// Fill out the out parameters: status new generation and log
//
pOutParams->SetDWORD(L"ReturnValue", (DWORD) Status); pOutParams->SetDWORD(L"NewGeneration", (DWORD) NewGeneration); if (pLog != NULL) { pOutParams->SetCHString(L"Log", pLog); delete pLog; pLog = NULL; }
//
// If we've actually called DoUpdate,
// we always return WBEM_NO_ERROR. The return value has the
// real result.
//
Status = WBEM_NO_ERROR;
end:
if (pSA!=NULL) { SafeArrayDestroy(pSA); pSA = NULL; }
TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
return Status;
}
WBEMSTATUS ProvQueryConfigurationUpdateStatus( CInstance *pInParams, CInstance *pOutParams ) /*++
WMI provider wrapper around NlbConfigurationUpdate::GetUpdateStatus
--*/ { if (!g_UpdateConfigurationEnabled) return WBEM_E_PROVIDER_NOT_CAPABLE;
LPCWSTR pAdapterGuid = NULL; WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE; CHString sTemp; bool fRet; DWORD Generation = 0;
/*
[IN] String AdapterGuid, [IN] uint32 Generation, [OUT] String Log */
fRet = pInParams->GetCHString( L"AdapterGuid", sTemp); if (!fRet) { TRACE_CRIT("->%!FUNC!: Missing adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; }
//
// Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
// buffer -- see operator LPCWSTR() of WString docs.
//
pAdapterGuid = (LPCWSTR) sTemp;
if (pAdapterGuid == NULL || *pAdapterGuid == 0) { TRACE_CRIT("->%!FUNC!: Null of empty adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; } else { TRACE_VERB(L"->%!FUNC!(Nic=%ws)", pAdapterGuid); }
fRet = pInParams->GetDWORD( L"Generation", // <--------------------------------
Generation ); if (!fRet) { TRACE_CRIT("%!FUNC!: Missing generation!"); Status = WBEM_E_INVALID_PARAMETER; goto end; }
//
// Call NlbConfigurationUpdate::GetUpdateResult to do the actual work.
//
LPWSTR pLog = NULL; WBEMSTATUS CompletionStatus = WBEM_NO_ERROR;
Status = NlbConfigurationUpdate::GetUpdateStatus( pAdapterGuid, Generation, FALSE, // FALSE == Don't delete completion record
&CompletionStatus, &pLog );
if (!FAILED(Status)) { //
// Fill out the out parameters: status new generation and log
//
pOutParams->SetDWORD(L"ReturnValue", (DWORD) CompletionStatus); if (pLog != NULL) { pOutParams->SetCHString(L"Log", pLog); delete pLog; pLog = NULL; } }
end:
TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
return Status;
}
|