windows-nt/Source/XPSP1/NT/net/wlbs/nlbmgr/provider/nlbsnic.cpp
2020-09-26 16:20:57 +08:00

1810 lines
54 KiB
C++

/******************************************************************
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;
}