|
|
#include "CommonNLB.h"
#include "MNLBCluster.h"
#include "MNLBHost.h"
#include "MNLBMachine.h"
#include "MNLBNetCfg.h"
#include "MWmiError.h"
#include "MUsingCom.h"
#include "MIPAddressAdmin.h"
#include "ResourceString.h"
#include "resource.h"
#include <vector>
#include <memory>
#include <algorithm>
#include <algorithm>
using namespace std;
// global only temporarily.
//
LeftView* g_leftView;
CommonNLB::CommonNLB_Error CommonNLB::connectToClusterDirect( const _bstr_t& clusterIP, const _bstr_t& hostMember, ClusterData* p_clusterData, DataSinkI* dataSinkObj ) {
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_CONNECTING) + hostMember );
MNLBMachine nlbMachine( hostMember, clusterIP );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE) );
vector<MNLBMachine::HostInfo> hostInfo;
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_FINDING_H ) );
nlbMachine.getPresentHostsInfo( &hostInfo );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE) );
vector< _bstr_t> connectionIPS;
for( int i = 0; i < hostInfo.size(); ++i ) { connectionIPS.push_back( hostInfo[i].dedicatedIP ); }
#if 1
return connectToClusterIndirect( clusterIP, connectionIPS, p_clusterData, dataSinkObj ); #else
vector<ClusterData> clusterDataStore; bool clusterPropertiesMatched;
connectToClusterIndirectNew( clusterIP, connectionIPS, &clusterDataStore, clusterPropertiesMatched, dataSinkObj ); (*p_clusterData) = clusterDataStore[0];
return CommonNLB_SUCCESS; #endif
}
CommonNLB::CommonNLB_Error CommonNLB::connectToClusterIndirectNew( const _bstr_t& clusterIP, const vector<_bstr_t>& connectionIPS, vector< ClusterData>* clusterDataStore, bool& clusterPropertiesMatched, DataSinkI* dataSinkObj )
{ // connect to each host.
// We are doing it here so that if there are any connectivity issues
// we do not proceed with any further operation and ask user to
// fix all issues before proceeding.
// connect to each host.
map< bstr_t, auto_ptr<MNLBMachine> > nlbMachine;
for( int i = 0; i < connectionIPS.size(); ++i ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_CONNECTING) + connectionIPS[i] );
auto_ptr<MNLBMachine> p_nlbMachine = auto_ptr<MNLBMachine> ( new MNLBMachine( connectionIPS[i], clusterIP ) ); nlbMachine[connectionIPS[i] ] = p_nlbMachine;
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE) ); }
// get information from each host.
//
for( int i = 0; i < connectionIPS.size(); ++i ) {
ClusterData clusterData; // get cluster properties.
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_FINDING_CL_P ) );
ClusterProperties cp;
nlbMachine[connectionIPS[i] ]->getClusterProperties( &cp );
clusterData.cp = cp;
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE) );
// get host properties.
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_FINDING_H_P ) );
HostProperties hp;
nlbMachine[connectionIPS[i] ]->getHostProperties( &hp );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE) );
// set the host properties
HostData hostData;
hostData.hp = hp;
// set the connection ip.
hostData.connectionIP = connectionIPS[i];
clusterData.hosts[hp.machineName] = hostData;
// get port rules
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_FINDING_P ) );
vector<MNLBPortRuleLoadBalanced> portsLB; vector<MNLBPortRuleFailover> portsF; vector<MNLBPortRuleDisabled> portsD;
PortDataULB ulbPortRule;
PortDataF fPortRule;
PortDataELB elbPortRule;
PortDataD dPortRule;
nlbMachine[connectionIPS[i] ]->getPortRulesLoadBalanced( &portsLB ); for( int j = 0; j < portsLB.size(); ++j ) { if( portsLB[j]._isEqualLoadBalanced == true ) { // equal load balanced port rule.
elbPortRule._startPort = portsLB[j]._startPort; elbPortRule._key = portsLB[j]._startPort; elbPortRule._endPort = portsLB[j]._endPort; elbPortRule._trafficToHandle = portsLB[j]._trafficToHandle; elbPortRule._affinity = portsLB[j]._affinity;
clusterData.portELB[portsLB[j]._startPort] = elbPortRule; } else { ulbPortRule._startPort = portsLB[j]._startPort; ulbPortRule._key = portsLB[j]._startPort; ulbPortRule._endPort = portsLB[j]._endPort; ulbPortRule._trafficToHandle = portsLB[j]._trafficToHandle; ulbPortRule._affinity = portsLB[j]._affinity;
ulbPortRule.machineMapToLoadWeight[hp.machineName] = portsLB[j]._load;
clusterData.portULB[portsLB[j]._startPort] = ulbPortRule; } } portsLB.erase( portsLB.begin(), portsLB.end() );
nlbMachine[connectionIPS[i] ]->getPortRulesFailover( &portsF ); for( int j = 0; j < portsF.size(); ++j ) { fPortRule._startPort = portsF[j]._startPort; fPortRule._key = portsF[j]._startPort; fPortRule._endPort = portsF[j]._endPort; fPortRule._trafficToHandle = portsF[j]._trafficToHandle;
fPortRule.machineMapToPriority[ hp.machineName] = portsF[j]._priority; clusterData.portF[portsF[j]._startPort] = fPortRule; } portsF.erase( portsF.begin(), portsF.end() );
// disabled port rules
nlbMachine[connectionIPS[i] ]->getPortRulesDisabled( &portsD );
for( int j = 0; j < portsD.size(); ++j ) { dPortRule._startPort = portsD[j]._startPort; dPortRule._key = portsD[j]._startPort; dPortRule._endPort = portsD[j]._endPort; dPortRule._trafficToHandle = portsD[j]._trafficToHandle; clusterData.portD[portsD[j]._startPort] = dPortRule; } portsD.erase( portsD.begin(), portsD.end() );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE) );
// get virtual ips. These have already been got when we got the host properties
// Thus here we are storing duplicate data, but this does ease
// a lot of data structure manipulation.
//
clusterData.virtualIPs = clusterData.hosts[hp.machineName].hp.nicInfo.ipsOnNic; clusterData.virtualSubnets = clusterData.hosts[hp.machineName].hp.nicInfo.subnetMasks;
clusterData.hosts[hp.machineName] = hostData;
clusterDataStore->push_back( clusterData );
}
// now we will verify whether the cluster is
// converged or there are mismatches.
// rules for a converged cluster.
//
// cluster properties which need to
// be same:
// cluster ip
// cluster subnet
// full internet name
// cluster mode
// remote Control Enabled.
//
// host properties
// host id has to be unique across hosts any
// number from 1-32 inclusive.
//
// port rules
// equal load balanced port rules have to be same
// disabled port rules have to be same.
// unequal load balanced port rules can differ only in load.
// single host port rules can differ in priority, which has to be
// unique across hosts for a specific port rule any number between 1-32.
//
// Each machine must have the cluster ip.
//
// Each machine must have the exactly same ips on the nic.
clusterPropertiesMatched = true;
// check if cluster ip is added.
//
if( find( (*clusterDataStore)[0].virtualIPs.begin(), (*clusterDataStore)[0].virtualIPs.end(), (*clusterDataStore)[0].cp.cIP ) == (*clusterDataStore)[0].virtualIPs.end() ) { clusterPropertiesMatched = false; }
if( clusterDataStore->size() == 1 ) { // only one host in cluster so only
return CommonNLB_SUCCESS; } // sort the virtual ips of the first node. Eases
// comparision.
sort( (*clusterDataStore)[0].virtualIPs.begin(), (*clusterDataStore)[0].virtualIPs.end() );
for( int i = 1; i < clusterDataStore->size(); ++i ) { // cluster properties must match.
//
if( (*clusterDataStore)[0].cp != (*clusterDataStore)[i].cp ) { // mismatch in cluster properties.
// MISMATCH
clusterPropertiesMatched = false; }
// the ELB, ULB, F, D port rules have to
// match.
if ( (*clusterDataStore)[0].portELB.size() != (*clusterDataStore)[i].portELB.size() ) { // mismatch in port rules.
// MISMATCH
clusterPropertiesMatched = false; } else { // number of port rules are matching.
map<long, PortDataELB>::iterator top; map<long, PortDataELB>::iterator location; for( top = (*clusterDataStore)[i].portELB.begin(); top != (*clusterDataStore)[i].portELB.end(); ++top ) { location = (*clusterDataStore)[0].portELB.find( (*top).first ); if( location == (*clusterDataStore)[0].portELB.end() ) { // no such port exists.
// thus mismatch.
// MISMATCH
clusterPropertiesMatched = false; } else { if( (*location).second._startPort != (*top).second._startPort || (*location).second._endPort != (*top).second._endPort || (*location).second._trafficToHandle != (*top).second._trafficToHandle || (*location).second._affinity != (*top).second._affinity ) { // things other than key which is start port
// has been modified.
// MISMATCH
} } } }
if ( (*clusterDataStore)[0].portULB.size() != (*clusterDataStore)[i].portULB.size() ) { // mismatch in port rules.
// MISMATCH
clusterPropertiesMatched = false; } else { // number of port rules are matching.
map<long, PortDataULB>::iterator top; map<long, PortDataULB>::iterator location; for( top = (*clusterDataStore)[i].portULB.begin(); top != (*clusterDataStore)[i].portULB.end(); ++top ) { location = (*clusterDataStore)[0].portULB.find( (*top).first ); if( location == (*clusterDataStore)[0].portULB.end() ) { // no such port exists.
// thus mismatch.
// MISMATCH
clusterPropertiesMatched = false; } else { if( (*location).second._startPort != (*top).second._startPort || (*location).second._endPort != (*top).second._endPort || (*location).second._trafficToHandle != (*top).second._trafficToHandle || (*location).second._affinity != (*top).second._affinity ) { // things other than key which is start port
// has been modified.
// MISMATCH
clusterPropertiesMatched = false; } } }
}
if ( (*clusterDataStore)[0].portF.size() != (*clusterDataStore)[i].portF.size() ) { // mismatch in port rules.
// MISMATCH
clusterPropertiesMatched = false; } else { // number of port rules are matching.
map<long, PortDataF>::iterator top; map<long, PortDataF>::iterator location; for( top = (*clusterDataStore)[i].portF.begin(); top != (*clusterDataStore)[i].portF.end(); ++top ) { location = (*clusterDataStore)[0].portF.find( (*top).first ); if( location == (*clusterDataStore)[0].portF.end() ) { // no such port exists.
// thus mismatch.
// MISMATCH
clusterPropertiesMatched = false; } else { if( (*location).second._startPort != (*top).second._startPort || (*location).second._endPort != (*top).second._endPort || (*location).second._trafficToHandle != (*top).second._trafficToHandle ) { // things other than key which is start port
// has been modified.
// MISMATCH
clusterPropertiesMatched = false; } } } }
if ( (*clusterDataStore)[0].portD.size() != (*clusterDataStore)[i].portD.size() ) { // mismatch in port rules.
// MISMATCH
clusterPropertiesMatched = false; } else { // number of port rules are matching.
map<long, PortDataD>::iterator top; map<long, PortDataD>::iterator location; for( top = (*clusterDataStore)[i].portD.begin(); top != (*clusterDataStore)[i].portD.end(); ++top ) { location = (*clusterDataStore)[0].portD.find( (*top).first ); if( location == (*clusterDataStore)[0].portD.end() ) { // no such port exists.
// thus mismatch.
// MISMATCH
clusterPropertiesMatched = false; } else { if( (*location).second._startPort != (*top).second._startPort || (*location).second._endPort != (*top).second._endPort || (*location).second._trafficToHandle != (*top).second._trafficToHandle ) { // things other than key which is start port
// has been modified.
// MISMATCH
clusterPropertiesMatched = false; } } } }
// check if each machine has the same virtual ips.
//
sort( (*clusterDataStore)[i].virtualIPs.begin(), (*clusterDataStore)[i].virtualIPs.end() );
if( (*clusterDataStore)[0].virtualIPs != (*clusterDataStore)[i].virtualIPs ) { // MISMATCH
clusterPropertiesMatched = false; } }
// check if host ids are duplicate.
map< _bstr_t, HostData>::iterator onlyHost; set<int> hostIDS;
for( int i = 0; i < clusterDataStore->size(); ++i ) { onlyHost = (*clusterDataStore)[i].hosts.begin();
// check if this host id has been used previously.
if( hostIDS.find( (*onlyHost).second.hp.hID ) == hostIDS.end() ) { // host id is unused.
hostIDS.insert( (*onlyHost).second.hp.hID ); } else { // host id has been used previously.
// Thus this is duplicate.
// MISMATCH
clusterPropertiesMatched = false; } }
if( clusterPropertiesMatched == true ) { // combine all the host information.
//
map<_bstr_t, HostData >::iterator top; for( int i = 1; i < clusterDataStore->size(); ++i ) { top = (*clusterDataStore)[i].hosts.begin();
(*clusterDataStore)[0].hosts[ (*top).first ] = (*top).second; }
#if 1
// combine all the port information for ULB and disabled port rules.
// this may be a little difficult, but it works. Don't fiddle around
// with this part.
map<long, PortDataULB>::iterator topULB; for( topULB = (*clusterDataStore)[0].portULB.begin(); topULB != (*clusterDataStore)[0].portULB.end(); ++topULB ) { map<_bstr_t, long>& ref = (*topULB).second.machineMapToLoadWeight; for( int i = 1; i < clusterDataStore->size(); ++i ) { // find the machine name for this clusterdata.
map<_bstr_t, HostData>::iterator top;
top = (*clusterDataStore)[i].hosts.begin();
_bstr_t machineName = (*top).first;
ref[machineName] = (*clusterDataStore)[i].portULB[ (*topULB).first ].machineMapToLoadWeight[ machineName]; } }
map<long, PortDataF>::iterator topF; for( topF = (*clusterDataStore)[0].portF.begin(); topF != (*clusterDataStore)[0].portF.end(); ++topF ) { map<_bstr_t, long>& ref = (*topF).second.machineMapToPriority; for( int i = 1; i < clusterDataStore->size(); ++i ) { // find the machine name for this clusterdata.
map<_bstr_t, HostData>::iterator top;
top = (*clusterDataStore)[i].hosts.begin();
_bstr_t machineName = (*top).first;
ref[machineName] = (*clusterDataStore)[i].portF[ (*topF).first ].machineMapToPriority[ machineName]; } }
#endif
}
return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::connectToClusterIndirect( const _bstr_t& clusterIP, const vector<_bstr_t>& connectionIPS, ClusterData* p_clusterData, DataSinkI* dataSinkObj ) { // connect to each host.
// We are doing it here so that if there are any connectivity issues
// we do not proceed with any further operation and ask user to
// fix all issues before proceeding.
// connect to each host.
map< bstr_t, auto_ptr<MNLBMachine> > nlbMachine;
for( int i = 0; i < connectionIPS.size(); ++i ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_CONNECTING) + connectionIPS[i] );
auto_ptr<MNLBMachine> p_nlbMachine = auto_ptr<MNLBMachine> ( new MNLBMachine( connectionIPS[i], clusterIP ) ); nlbMachine[connectionIPS[i] ] = p_nlbMachine;
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE) ); }
// rules for a converged cluster.
//
// cluster properties which need to
// be same:
// cluster ip
// cluster subnet
// full internet name
// cluster mode
//
// host properties
// host id has to be unique across hosts any
// number from 1-32 inclusive.
//
// port rules
// equal load balanced port rules have to be same
// disabled port rules have to be same.
// unequal load balanced port rules can differ only in load.
// single host port rules can differ in priority, which has to be
// unique across hosts for a specific port rule any number between 1-32.
//
for( int i = 0; i < connectionIPS.size(); ++i ) { // get cluster properties.
// cluster properties need to be got only for one host.
if( i == 0 ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_FINDING_CL_P ) );
ClusterProperties cp;
nlbMachine[connectionIPS[i] ]->getClusterProperties( &cp );
p_clusterData->cp = cp;
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE) );
}
// get host properties.
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_FINDING_H_P ) );
HostProperties hp;
nlbMachine[connectionIPS[i] ]->getHostProperties( &hp );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE) );
// set the host properties
HostData hostData;
hostData.hp = hp;
// set the connection ip.
hostData.connectionIP = connectionIPS[i];
p_clusterData->hosts[hp.machineName] = hostData;
// get port rules
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_FINDING_P ) );
vector<MNLBPortRuleLoadBalanced> portsLB; vector<MNLBPortRuleFailover> portsF; vector<MNLBPortRuleDisabled> portsD;
PortDataULB ulbPortRule;
PortDataF fPortRule;
PortDataELB elbPortRule;
PortDataD dPortRule;
nlbMachine[connectionIPS[i] ]->getPortRulesLoadBalanced( &portsLB ); for( int j = 0; j < portsLB.size(); ++j ) { if( portsLB[j]._isEqualLoadBalanced == true ) { // equal load balanced port rule.
elbPortRule._startPort = portsLB[j]._startPort; elbPortRule._key = portsLB[j]._startPort; elbPortRule._endPort = portsLB[j]._endPort; elbPortRule._trafficToHandle = portsLB[j]._trafficToHandle; elbPortRule._affinity = portsLB[j]._affinity;
p_clusterData->portELB[portsLB[j]._startPort] = elbPortRule; } else { // unequal load balanced.
if( i == 0 ) { ulbPortRule._startPort = portsLB[j]._startPort; ulbPortRule._key = portsLB[j]._startPort; ulbPortRule._endPort = portsLB[j]._endPort; ulbPortRule._trafficToHandle = portsLB[j]._trafficToHandle; ulbPortRule._affinity = portsLB[j]._affinity;
ulbPortRule.machineMapToLoadWeight[hp.machineName] = portsLB[j]._load;
p_clusterData->portULB[portsLB[j]._startPort] = ulbPortRule; } else { p_clusterData->portULB[portsLB[j]._startPort].machineMapToLoadWeight[ hp.machineName] = portsLB[j]._load; } } } portsLB.erase( portsLB.begin(), portsLB.end() );
nlbMachine[connectionIPS[i] ]->getPortRulesFailover( &portsF ); for( int j = 0; j < portsF.size(); ++j ) { if( i == 0 ) { fPortRule._startPort = portsF[j]._startPort; fPortRule._key = portsF[j]._startPort; fPortRule._endPort = portsF[j]._endPort; fPortRule._trafficToHandle = portsF[j]._trafficToHandle;
fPortRule.machineMapToPriority[ hp.machineName] = portsF[j]._priority; p_clusterData->portF[portsF[j]._startPort] = fPortRule; } else { p_clusterData->portF[portsF[j]._startPort].machineMapToPriority[ hp.machineName] = portsF[j]._priority; } } portsF.erase( portsF.begin(), portsF.end() );
// disabled need to be got only once.
if( i == 0 ) { nlbMachine[connectionIPS[i] ]->getPortRulesDisabled( &portsD );
for( int j = 0; j < portsD.size(); ++j ) { dPortRule._startPort = portsD[j]._startPort; dPortRule._key = portsD[j]._startPort; dPortRule._endPort = portsD[j]._endPort; dPortRule._trafficToHandle = portsD[j]._trafficToHandle;
p_clusterData->portD[portsD[j]._startPort] = dPortRule; } portsD.erase( portsD.begin(), portsD.end() ); }
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE) ); }
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_SUCCESS ) );
return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::connectToMachine( const _bstr_t& machineToConnect, _bstr_t& machineServerName, vector< CommonNLB::NicNLBBound >& nicList, DataSinkI* dataSinkObj ) { // connect to machine.
//
MWmiObject machine( machineToConnect, L"root\\microsoftnlb", L"administrator", L"" );
// find all nics on machine.
//
vector<MWmiInstance> instanceStore; machine.getInstances( L"NlbsNic", &instanceStore );
// check if nic has nlb bound.
//
// input parameters are none.
//
vector<MWmiParameter *> inputParameters;
// output parameters which are of interest.
//
vector<MWmiParameter *> outputParameters; MWmiParameter ReturnValue(L"ReturnValue"); outputParameters.push_back( &ReturnValue );
vector<MWmiParameter *> parameterStore;
MWmiParameter Server(L"__Server"); parameterStore.push_back( &Server );
MWmiParameter FullName(L"FullName"); parameterStore.push_back( &FullName );
MWmiParameter AdapterGuid(L"AdapterGuid"); parameterStore.push_back( &AdapterGuid );
MWmiParameter FriendlyName(L"FriendlyName"); parameterStore.push_back( &FriendlyName );
for( int i = 0; i < instanceStore.size(); ++i ) { // get full name, guid and friendly name.
//
NicNLBBound temp;
instanceStore[i].getParameters( parameterStore ); temp.fullNicName = FullName.getValue(); temp.adapterGuid = AdapterGuid.getValue(); temp.friendlyName = FriendlyName.getValue();
// get machine name.
machineServerName = Server.getValue();
// check if nic is bound to nlb or not.
instanceStore[i].runMethod( L"isBound", inputParameters, outputParameters ); if( long( ReturnValue.getValue() ) == 1 ) { // this nic is bound.
temp.isBoundToNLB = true; } else { temp.isBoundToNLB = false; }
// get all the ip's on this nic.
MIPAddressAdmin ipAdmin( machineToConnect, temp.fullNicName );
ipAdmin.getIPAddresses( &temp.ipsOnNic, &temp.subnetMasks );
// check if the nic is dhcp.
ipAdmin.isDHCPEnabled( temp.dhcpEnabled ); nicList.push_back( temp ); }
return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::changeNLBClusterSettings( const ClusterData* oldSettings, const ClusterData* newSettings, DataSinkI* dataSinkObj ) { return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::changeNLBHostSettings( const ClusterData* oldSettings, const ClusterData* newSettings, const _bstr_t& machineName, DataSinkI* dataSinkObj ) { ClusterData* oldSettingsCopy = const_cast <ClusterData *>( oldSettings ); ClusterData* newSettingsCopy = const_cast <ClusterData *>( newSettings );
map<_bstr_t, HostData>::iterator topOld; map<_bstr_t, HostData>::iterator topNew;
// change host properties for host if that have changed.
//
if( oldSettingsCopy->hosts[machineName].hp != newSettingsCopy->hosts[machineName].hp ) { // connect to machine.
//
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_CONNECTING ) + oldSettingsCopy->hosts[machineName].connectionIP );
MNLBMachine nlbMachine( oldSettingsCopy->hosts[machineName].connectionIP, oldSettingsCopy->cp.cIP ); dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE) ); dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_MODIFYING_H_P ) );
// host properties have changed.
unsigned long returnValue; nlbMachine.setHostProperties( newSettingsCopy->hosts[machineName].hp, &returnValue );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE) ); }
return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::changeNLBHostPortSettings( const ClusterData* oldSettings, const ClusterData* newSettings, const _bstr_t& machineName, DataSinkI* dataSinkObj ) { ClusterData* oldSettingsCopy = const_cast <ClusterData *>( oldSettings ); ClusterData* newSettingsCopy = const_cast <ClusterData *>( newSettings );
map<_bstr_t, HostData>::iterator topOld; map<_bstr_t, HostData>::iterator topNew;
// connect to machine.
//
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_CONNECTING ) + oldSettingsCopy->hosts[machineName].connectionIP );
MNLBMachine nlbMachine( oldSettingsCopy->hosts[machineName].connectionIP, oldSettingsCopy->cp.cIP );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE ) );
// check if any load weights have changed.
// for any unequal load balanced port rule.
//
map<long, PortDataULB>::iterator topOldULB; map<long, PortDataULB>::iterator topNewULB;
for( topOldULB = oldSettingsCopy->portULB.begin(), topNewULB = newSettingsCopy->portULB.begin(); topOldULB != oldSettingsCopy->portULB.end(); ++topOldULB, ++topNewULB ) { if( (*topOldULB).second.machineMapToLoadWeight[machineName] != (*topNewULB).second.machineMapToLoadWeight[machineName] ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_MODIFYING_P_ULB ) );
// load weight has changed.
// remove old port rule
MNLBPortRuleLoadBalanced portULB = (*topNewULB).second; portULB._load = (*topOldULB).second.machineMapToLoadWeight[machineName];
nlbMachine.removePortRuleLoadBalanced( portULB );
// add this port rule.
// only load weight can change.
portULB._load = (*topNewULB).second.machineMapToLoadWeight[machineName];
nlbMachine.addPortRuleLoadBalanced( portULB );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE ) ); } }
// check if any priorities have changed.
// for any failover port rules
//
map<long, PortDataF>::iterator topOldF; map<long, PortDataF>::iterator topNewF;
for( topOldF = oldSettingsCopy->portF.begin(), topNewF = newSettingsCopy->portF.begin(); topOldF != oldSettingsCopy->portF.end(); ++topOldF, ++topNewF ) { if( (*topOldF).second.machineMapToPriority[machineName] != (*topNewF).second.machineMapToPriority[machineName] ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_MODIFYING_P_F ) );
// priority has changed.
MNLBMachine nlbMachine( newSettingsCopy->hosts[machineName].connectionIP, newSettingsCopy->cp.cIP );
// remove old port rule
MNLBPortRuleFailover portF = (*topNewF).second; portF._priority = (*topOldF).second.machineMapToPriority[machineName];
nlbMachine.removePortRuleFailover( portF );
// add new port rule.
// only priority has changed.
portF._priority = (*topNewF).second.machineMapToPriority[machineName];
nlbMachine.addPortRuleFailover( portF );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE ) ); } }
return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::changeNLBClusterAndPortSettings( const ClusterData* oldSettings, const ClusterData* newSettings, DataSinkI* dataSinkObj, bool* pbClusterIpChanged) { ClusterData* oldSettingsCopy = const_cast <ClusterData *>( oldSettings ); ClusterData* newSettingsCopy = const_cast <ClusterData *>( newSettings ); bool bClusterParametersChanged, bPortRulesChanged, bOnlyClusterNameChanged;
// Find out if the cluster parameters have changed. Also, find if the cluster name
// is the only parameter that has changed
bClusterParametersChanged = newSettingsCopy->cp.HaveClusterPropertiesChanged(oldSettingsCopy->cp, &bOnlyClusterNameChanged, pbClusterIpChanged); vector<long> rulesAddedELB; vector<long> rulesUnchangedELB; vector<long> rulesRemovedELB;
findPortRulesAddedUnchangedRemovedELB( oldSettingsCopy, newSettingsCopy, dataSinkObj, rulesAddedELB, rulesUnchangedELB, rulesRemovedELB );
vector<long> rulesAddedULB; vector<long> rulesUnchangedULB; vector<long> rulesRemovedULB;
findPortRulesAddedUnchangedRemovedULB( oldSettingsCopy, newSettingsCopy, dataSinkObj, rulesAddedULB, rulesUnchangedULB, rulesRemovedULB );
vector<long> rulesAddedD; vector<long> rulesUnchangedD; vector<long> rulesRemovedD;
findPortRulesAddedUnchangedRemovedD( oldSettingsCopy, newSettingsCopy, dataSinkObj, rulesAddedD, rulesUnchangedD, rulesRemovedD );
vector<long> rulesAddedF; vector<long> rulesUnchangedF; vector<long> rulesRemovedF;
findPortRulesAddedUnchangedRemovedF( oldSettingsCopy, newSettingsCopy, dataSinkObj, rulesAddedF, rulesUnchangedF, rulesRemovedF );
// check if any port rules have been added or removed
// if not we don't want to do anything.
if( ( rulesAddedULB.size() == 0 ) && ( rulesRemovedULB.size() == 0 ) && ( rulesAddedELB.size() == 0 ) && ( rulesRemovedELB.size() == 0 ) && ( rulesAddedD.size() == 0 ) && ( rulesRemovedD.size() == 0 ) && ( rulesAddedF.size() == 0 ) && ( rulesRemovedF.size() == 0 ) ) { //return CommonNLB_SUCCESS;
//OutputDebugString(_T("No Change to Port Rules\n"));
bPortRulesChanged = false; } else { bPortRulesChanged = true; }
// Neither the cluster parameters nor the port rules have changed, so return
if (!bClusterParametersChanged && !bPortRulesChanged) { //OutputDebugString(_T("No Change to Cluster Parameters or Port Rules\n"));
return CommonNLB_SUCCESS; }
// connect to each host.
// We are doing it here so that if there are any connectivity issues
// we do not proceed with any changes and just inform the user.
// This is to ensure that we do not cause any convergence.
// connect to each host.
map<_bstr_t, HostData >::iterator top; map< bstr_t, auto_ptr<MNLBMachine> > nlbMachine;
for( top = oldSettingsCopy->hosts.begin(); top != oldSettingsCopy->hosts.end(); ++top ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_CONNECTING ) + (*top).second.connectionIP );
auto_ptr<MNLBMachine> p_nlbMachine = auto_ptr<MNLBMachine> ( new MNLBMachine( (*top).second.connectionIP, oldSettingsCopy->cp.cIP ) ); nlbMachine[(*top).first] = p_nlbMachine;
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE ) );
}
// for each host in cluster apply the changed port & cluster rules.
for( top = oldSettingsCopy->hosts.begin(); top != oldSettingsCopy->hosts.end(); ++top ) { if (bPortRulesChanged) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_MODIFYING_P ) );
// remove all port rules which need to be erased..
//
for( int i = 0; i < rulesRemovedELB.size(); ++i ) { nlbMachine[ (*top).first ]->removePortRuleLoadBalanced( oldSettingsCopy->portELB[ rulesRemovedELB[i] ] ); }
for( int i = 0; i < rulesRemovedULB.size(); ++i ) { nlbMachine[ (*top).first ]->removePortRuleLoadBalanced( oldSettingsCopy->portULB[ rulesRemovedULB[i] ] ); }
for( int i = 0; i < rulesRemovedD.size(); ++i ) { nlbMachine[ (*top).first ]->removePortRuleDisabled( oldSettingsCopy->portD[ rulesRemovedD[i] ] ); }
for( int i = 0; i < rulesRemovedF.size(); ++i ) { nlbMachine[ (*top).first ]->removePortRuleFailover( oldSettingsCopy->portF[rulesRemovedF[i] ] ); }
// add all new port rules
//
for( int i = 0; i < rulesAddedELB.size(); ++i ) { nlbMachine[ (*top).first ]->addPortRuleLoadBalanced( newSettingsCopy->portELB[ rulesAddedELB[i] ] ); } for( int i = 0; i < rulesAddedULB.size(); ++i ) { MNLBPortRuleLoadBalanced portULB = newSettingsCopy->portULB[ rulesAddedULB[i] ];
_bstr_t machineName = (*top).first;
portULB._load = newSettingsCopy->portULB[rulesAddedULB[i]].machineMapToLoadWeight[ (*top).first ]; nlbMachine[ (*top).first ]->addPortRuleLoadBalanced( portULB ); }
for( int i = 0; i < rulesAddedD.size(); ++i ) { nlbMachine[ (*top).first ]->addPortRuleDisabled( newSettingsCopy->portD[rulesAddedD[i] ] ); }
for( int i = 0; i < rulesAddedF.size(); ++i ) { MNLBPortRuleFailover portF = newSettingsCopy->portF[rulesAddedF[i] ]; portF._priority = newSettingsCopy->portF[rulesAddedF[i]].machineMapToPriority[ (*top).first ]; nlbMachine[ (*top).first ]->addPortRuleFailover( portF ); } dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE ) ); } if (bClusterParametersChanged) { if (bOnlyClusterNameChanged) { unsigned long retVal; dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_MODIFYING_CN ) ); nlbMachine[ (*top).first ]->setClusterProperties(newSettingsCopy->cp, &retVal);
// if remote control is enabled set the password.
// even if password has not changed just making extra call.
if( newSettingsCopy->cp.remoteControlEnabled == true ) { nlbMachine[ (*top).first ]->setPassword(newSettingsCopy->cp.password, &retVal); }
} else // Cluster Parameters other than Cluster name have changed too
{ dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_REMOVING_CL_IP ) ); MNLBNetCfg nlbNetCfg((*top).second.connectionIP, (*top).second.hp.nicInfo.fullNicName); nlbNetCfg.removeClusterIP(oldSettingsCopy->cp.cIP); } dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE ) ); } }
// If Cluster Paraters other than the Cluster Name has changed, call the NLB Manager
// provider's "ModifyClusterProperties" (eventually) to modify cluster properties
// and add the cluster ip to tcp/ip. Modification of the cluster properties will
// result in the disable/re-enable of the nic & hence the WMI DCOM connection might
// be lost. So, we are doing this two-step operation locally
if (bClusterParametersChanged && !bOnlyClusterNameChanged) { for( top = oldSettingsCopy->hosts.begin(); top != oldSettingsCopy->hosts.end(); ++top ) { //OutputDebugString(_T("Modifying Cluster Parameters and adding cluster ip to tcp-ip !!!\n"));
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_MODIFYING_CP_AND_ADD_IP ) );
MNLBNetCfg* p_nlbNetCfg = NULL; ModifyClusterPropertiesParameters* par = NULL; try { p_nlbNetCfg = new MNLBNetCfg((*top).second.connectionIP, (*top).second.hp.nicInfo.fullNicName);
par = new ModifyClusterPropertiesParameters;
par->nlbNetCfg = p_nlbNetCfg;
par->clusterData = NULL; par->clusterData = new ClusterData( *newSettingsCopy ); par->machineName = new _bstr_t( (*top).second.hp.machineName ); g_leftView = (LeftView *) dataSinkObj;
} catch(...) { delete par->clusterData; delete par; delete p_nlbNetCfg;
dataSinkObj->dataSink(GETRESOURCEIDSTRING(IDS_INFO_NEW_EXCEPTION)); throw; }
AfxBeginThread( (AFX_THREADPROC) ModifyClusterPropertiesThread, par );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE ) ); } } return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::findPortRulesAddedUnchangedRemovedELB( const ClusterData* oldSettings, const ClusterData* newSettings, DataSinkI* dataSinkObj, vector<long>& rulesAdded, vector<long>& rulesUnchanged, vector<long>& rulesRemoved ) { map<long, PortDataELB>::iterator top; map<long, PortDataELB>::iterator location;
// find ports which have been newly added or modified.
//
for( top = newSettings->portELB.begin(); top != newSettings->portELB.end(); ++top ) { rulesAdded.push_back( (*top).first ); } // find ports which have remain unchanged and ports which have
// been removed or modified.
for( top = oldSettings->portELB.begin(); top != oldSettings->portELB.end(); ++top ) { // check if this port rule has been removed or modified.
location = newSettings->portELB.find( (*top).first ); if( location == newSettings->portELB.end() ) { // key has been removed
rulesRemoved.push_back( (*top).first ); } else { // may be things other than key are modified or totally
// unchanged.
if( (*location).second == (*top).second ) { // totally unchanged
rulesUnchanged.push_back( (*top).first ); rulesAdded.erase (find( rulesAdded.begin(), rulesAdded.end(), (*top).first ) ); } else { // key is same but the other parts are modified.
rulesRemoved.push_back( (*top).first ); } } }
return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::findPortRulesAddedUnchangedRemovedULB( const ClusterData* oldSettings, const ClusterData* newSettings, DataSinkI* dataSinkObj, vector<long>& rulesAdded, vector<long>& rulesUnchanged, vector<long>& rulesRemoved ) { map<long, PortDataULB>::iterator top; map<long, PortDataULB>::iterator location;
// find ports which have been newly added or modified.
//
for( top = newSettings->portULB.begin(); top != newSettings->portULB.end(); ++top ) { rulesAdded.push_back( (*top).first ); } // find ports which have remain unchanged and ports which have
// been removed or modified.
for( top = oldSettings->portULB.begin(); top != oldSettings->portULB.end(); ++top ) { // check if this port rule has been removed or modified.
location = newSettings->portULB.find( (*top).first ); if( location == newSettings->portULB.end() ) { // key has been removed
rulesRemoved.push_back( (*top).first ); } else { // may be things other than key are modified or totally
// unchanged.
if( (*location).second == (*top).second ) { // totally unchanged
rulesUnchanged.push_back( (*top).first ); rulesAdded.erase (find( rulesAdded.begin(), rulesAdded.end(), (*top).first ) ); } else { // key is same but the other parts are modified.
rulesRemoved.push_back( (*top).first ); } } }
return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::findPortRulesAddedUnchangedRemovedD( const ClusterData* oldSettings, const ClusterData* newSettings, DataSinkI* dataSinkObj, vector<long>& rulesAdded, vector<long>& rulesUnchanged, vector<long>& rulesRemoved ) { map<long, PortDataD>::iterator top; map<long, PortDataD>::iterator location;
// find ports which have been newly added or modified.
//
for( top = newSettings->portD.begin(); top != newSettings->portD.end(); ++top ) { rulesAdded.push_back( (*top).first ); } // find ports which have remain unchanged and ports which have
// been removed or modified.
for( top = oldSettings->portD.begin(); top != oldSettings->portD.end(); ++top ) { // check if this port rule has been removed or modified.
location = newSettings->portD.find( (*top).first ); if( location == newSettings->portD.end() ) { // key has been removed
rulesRemoved.push_back( (*top).first ); } else { // may be things other than key are modified or totally
// unchanged.
if( (*location).second == (*top).second ) { // totally unchanged
rulesUnchanged.push_back( (*top).first ); rulesAdded.erase (find( rulesAdded.begin(), rulesAdded.end(), (*top).first ) ); } else { // key is same but the other parts are modified.
rulesRemoved.push_back( (*top).first ); } } }
return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::findPortRulesAddedUnchangedRemovedF( const ClusterData* oldSettings, const ClusterData* newSettings, DataSinkI* dataSinkObj, vector<long>& rulesAdded, vector<long>& rulesUnchanged, vector<long>& rulesRemoved ) { map<long, PortDataF>::iterator top; map<long, PortDataF>::iterator location;
// find ports which have been newly added or modified.
//
for( top = newSettings->portF.begin(); top != newSettings->portF.end(); ++top ) { rulesAdded.push_back( (*top).first ); } // find ports which have remain unchanged and ports which have
// been removed or modified.
for( top = oldSettings->portF.begin(); top != oldSettings->portF.end(); ++top ) { // check if this port rule has been removed or modified.
location = newSettings->portF.find( (*top).first ); if( location == newSettings->portF.end() ) { // key has been removed
rulesRemoved.push_back( (*top).first ); } else { // may be things other than key are modified or totally
// unchanged.
if( (*location).second == (*top).second ) { // totally unchanged
rulesUnchanged.push_back( (*top).first ); rulesAdded.erase (find( rulesAdded.begin(), rulesAdded.end(), (*top).first ) ); } else { // key is same but the other parts are modified.
rulesRemoved.push_back( (*top).first ); } } }
return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::removeCluster( const ClusterData* clusterSettings, DataSinkI* dataSinkObj ) { map<_bstr_t, HostData>::iterator top;
for( top = clusterSettings->hosts.begin(); top != clusterSettings->hosts.end(); ++top ) { removeHost( clusterSettings, (*top).first, dataSinkObj ); }
return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::removeHost( const ClusterData* clusterSettings, const _bstr_t& machineName, DataSinkI* dataSinkObj ) { ClusterData* clusterSettingsCopy = const_cast <ClusterData *>( clusterSettings );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_CONNECTING ) + clusterSettingsCopy->hosts[machineName].connectionIP );
// note that we are not responsible for freeing this pointer
// though if the removeClusterIP fails then we do need to free it.
// TODO
MNLBNetCfg* p_nlbNetCfg = new MNLBNetCfg( clusterSettingsCopy->hosts[machineName].connectionIP, clusterSettingsCopy->hosts[machineName].hp.nicInfo.fullNicName );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE ) ); dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_REMOVING_CL_IP ) + clusterSettingsCopy->cp.cIP );
// remove cluster ip from machine specified.
p_nlbNetCfg->removeClusterIP( clusterSettingsCopy->cp.cIP );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE ) );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_UNBINDING_NLB ) + clusterSettingsCopy->hosts[machineName].hp.nicInfo.fullNicName );
AfxBeginThread( (AFX_THREADPROC ) UnbindThread, p_nlbNetCfg );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_REQUEST ) );
return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::runControlMethodOnCluster( const ClusterData* clusterSettings, DataSinkI* dataSinkObj, const _bstr_t& methodToRun, unsigned long portToAffect ) { map<_bstr_t, HostData>::iterator top;
for( top = clusterSettings->hosts.begin(); top != clusterSettings->hosts.end(); ++top ) { runControlMethodOnHost( clusterSettings, (*top).first, dataSinkObj, methodToRun, portToAffect ); }
return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::runControlMethodOnHost( const ClusterData* clusterSettings, const _bstr_t& machineName, DataSinkI* dataSinkObj, const _bstr_t& methodToRun, unsigned long portToAffect ) { ClusterData* clusterSettingsCopy = const_cast <ClusterData *>( clusterSettings );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_CONNECTING ) + clusterSettingsCopy->hosts[machineName].connectionIP );
MNLBMachine nlbMachine( clusterSettingsCopy->hosts[machineName].connectionIP, clusterSettingsCopy->cp.cIP );
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_INFO_DONE ) );
unsigned long retVal; if( methodToRun == _bstr_t( L"query" ) ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_COMMAND_QUERY ) + clusterSettingsCopy->cp.cIP + L":" + machineName ); // the hoststatus has the current state of the host.
HostProperties hp; nlbMachine.getHostProperties( &hp ); retVal = hp.hostStatus;
} else if( methodToRun == _bstr_t( L"start" ) ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_COMMAND_START ) + clusterSettingsCopy->cp.cIP + L":" + machineName );
nlbMachine.start( Common::THIS_HOST, &retVal ); } else if( methodToRun == _bstr_t( L"stop" ) ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_COMMAND_STOP ) + clusterSettingsCopy->cp.cIP + L":" + machineName );
nlbMachine.stop( Common::THIS_HOST, &retVal ); } else if( methodToRun == _bstr_t( L"drainstop" ) ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_COMMAND_DRAINSTOP ) + clusterSettingsCopy->cp.cIP + L":" + machineName );
nlbMachine.drainstop( Common::THIS_HOST, &retVal ); } else if( methodToRun == _bstr_t( L"resume" ) ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_COMMAND_RESUME ) + clusterSettingsCopy->cp.cIP + L":" + machineName );
nlbMachine.resume( Common::THIS_HOST, &retVal ); } else if( methodToRun == _bstr_t( L"suspend" ) ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_COMMAND_SUSPEND ) + clusterSettingsCopy->cp.cIP + L":" + machineName );
nlbMachine.suspend( Common::THIS_HOST, &retVal ); } else if( methodToRun == _bstr_t( L"enable" ) ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_COMMAND_ENABLE ) + clusterSettingsCopy->cp.cIP + L":" + machineName );
nlbMachine.enable( Common::THIS_HOST, &retVal, portToAffect ); } else if( methodToRun == _bstr_t( L"disable" ) ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_COMMAND_DISABLE ) + clusterSettingsCopy->cp.cIP + L":" + machineName );
nlbMachine.disable( Common::THIS_HOST, &retVal, portToAffect ); } else if( methodToRun == _bstr_t( L"drain" ) ) { dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_COMMAND_DRAIN ) + clusterSettingsCopy->cp.cIP + L":" + machineName );
nlbMachine.drain( Common::THIS_HOST, &retVal, portToAffect ); } else { // unknown method. It has to be one of above.
dataSinkObj->dataSink( GETRESOURCEIDSTRING( IDS_WLBS_UNKNOWN ) ); }
// decipher the return.
_bstr_t errString; getWLBSErrorString( retVal, errString ); dataSinkObj->dataSink( errString );
return CommonNLB_SUCCESS; }
// the unbinding is done in a separate thread
// as this call though successful, unloads and reloads the nic
// when nlb is unbound which can cause the connection to fail.
// This failure can occur after a very long time, which causes nlb
// manager to hang if this operation is not carried out in
// separate thread.
// Also note that the ownership of the MNLBNetCfg object is given
// to this thread, thus it is deleting this object. Thus caller
// needs to create the object on the heap, pass it in AfxBeginThread
// and be sure to not delete it.
UINT CommonNLB::UnbindThread( LPVOID pParam ) { MUsingCom com;
MNLBNetCfg* p_nlbNetCfg = ( MNLBNetCfg *) pParam;
try { p_nlbNetCfg->unbind(); } catch( _com_error (e ) ) { // the above call may fail, thus we want
// to catch exception.
}
delete p_nlbNetCfg;
return 0; }
CommonNLB::CommonNLB_Error CommonNLB::getWLBSErrorString( unsigned long errStatus, // IN
_bstr_t& extErrString // OUT
) { switch( errStatus ) {
case 1000 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_OK ); break;
case 1001 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_ALREADY ); break;
case 1002 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_DRAIN_STOP ); break;
case 1003 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_BAD_PARAMS ); break;
case 1004 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_NOT_FOUND ); break;
case 1005 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_STOPPED ); break;
case 1006 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_CONVERGING ); break;
case 1007 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_CONVERGED ); break;
case 1008 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_DEFAULT ); break;
case 1009 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_DRAINING ); break;
case 1013 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_SUSPENDED ); break;
case 1050 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_REBOOT ); break;
case 1100 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_INIT_ERROR ); break;
case 1101 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_BAD_PASSW ); break;
case 1102: extErrString = GETRESOURCEIDSTRING( IDS_WLBS_IO_ERROR ); break; case 1103 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_TIMEOUT ); break;
case 1150 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_PORT_OVERLAP ); break;
case 1151 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_BAD_PORT_PARAMS ); break;
case 1152 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_MAX_PORT_RULES ); break;
case 1153 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_TRUNCATED ); break;
case 1154 : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_REG_ERROR ); break;
default : extErrString = GETRESOURCEIDSTRING( IDS_WLBS_UNKNOWN ); break; }
return CommonNLB_SUCCESS; }
CommonNLB::CommonNLB_Error CommonNLB::addHostToCluster( const ClusterData* clusterToAddTo, const _bstr_t& machineName, DataSinkI* dataSinkObj ) { ClusterData* clusterToAddToCopy = const_cast <ClusterData *>( clusterToAddTo );
MNLBNetCfg* p_nlbNetCfg = NULL; BindAndConfigureParameters* par = NULL;
try { p_nlbNetCfg = new MNLBNetCfg(clusterToAddToCopy->hosts[machineName].connectionIP, clusterToAddToCopy->hosts[machineName].hp.nicInfo.fullNicName );
par = new BindAndConfigureParameters;
g_leftView = (LeftView *) dataSinkObj;
par->nlbNetCfg = p_nlbNetCfg; par->clusterData = NULL; par->machineName = NULL; par->clusterData = new ClusterData( *clusterToAddToCopy ); par->machineName = new _bstr_t( machineName ); } catch(...) { if (par != NULL) { delete par->machineName; delete par->clusterData; delete par; } delete p_nlbNetCfg;
dataSinkObj->dataSink(GETRESOURCEIDSTRING(IDS_INFO_NEW_EXCEPTION)); throw; }
AfxBeginThread( (AFX_THREADPROC ) BindAndConfigureThread, par );
return CommonNLB_SUCCESS; }
// the binding and configuration is done in a separate thread
// as this call though successful, unloads and reloads the nic
// when nlb is bound which can cause the connection to fail.
// This failure can occur after a very long time, which causes nlb
// manager to hang if this operation is not carried out in
// separate thread.
// It is very important to ensure that you are completely sure
// that binding and configuration will succeed as this call will
// run in its separate thread and does not generate errors even if
// failure occurs.
//
// Also note that the ownership of the MNLBNetCfg object is given
// to this thread, thus it is deleting this object. Thus caller
// needs to create the object on the heap, pass it in AfxBeginThread
// and be sure to not delete it.
UINT CommonNLB::BindAndConfigureThread( LPVOID pParam ) { MUsingCom com;
BindAndConfigureParameters* parameters = ( BindAndConfigureParameters *) pParam;
MNLBNetCfg* p_nlbNetCfg = parameters->nlbNetCfg;
ClusterData* p_clusterData = parameters->clusterData;
_bstr_t* p_machineName = parameters->machineName;
try { p_nlbNetCfg->bindAndConfigure( p_clusterData, *p_machineName ); } catch( _com_error (e ) ) { // the above call may fail, thus we want
// to catch exception.
}
delete p_nlbNetCfg; delete p_clusterData; delete p_machineName;
delete parameters;
return 0; }
// the modification of cluster properties is done in a separate thread
// as this call though successful, might unload and reload the nic driver
// when nlb is bound which can cause the connection to fail.
// This failure can occur after a very long time, which causes nlb
// manager to hang if this operation is not carried out in
// separate thread.
// It is very important to ensure that you are completely sure
// that this operation will succeed as this call will
// run in its separate thread and does not generate errors even if
// failure occurs.
//
// Also note that the ownership of the MNLBNetCfg object is given
// to this thread, thus it is deleting this object. Thus caller
// needs to create the object on the heap, pass it in AfxBeginThread
// and be sure to not delete it.
UINT CommonNLB::ModifyClusterPropertiesThread( LPVOID pParam ) { MUsingCom com;
ModifyClusterPropertiesParameters* parameters = ( ModifyClusterPropertiesParameters *) pParam;
MNLBNetCfg* p_nlbNetCfg = parameters->nlbNetCfg;
ClusterProperties* p_clusterProperties = &(parameters->clusterData->cp);
try { p_nlbNetCfg->modifyClusterProperties(p_clusterProperties); } catch( _com_error (e ) ) { // the above call may fail, thus we want
// to catch exception.
}
delete p_nlbNetCfg; delete parameters->clusterData;
delete parameters;
return 0; }
UINT CommonNLB::DummyThread( LPVOID pParam ) { MUsingCom com;
Sleep( 1000 );
BindAndConfigureParameters* parameters = ( BindAndConfigureParameters *) pParam;
LeftView * leftView = g_leftView;
TVINSERTSTRUCT item; item.hParent = leftView->GetTreeCtrl().GetRootItem();
ClusterData* p_clusterDataItem; HTREEITEM hNextItem; HTREEITEM hChildItem;
if( leftView->GetTreeCtrl().ItemHasChildren( leftView->GetTreeCtrl().GetRootItem() ) ) { hChildItem = leftView->GetTreeCtrl().GetChildItem(leftView->GetTreeCtrl().GetRootItem() ); while (hChildItem != NULL) { hNextItem = leftView->GetTreeCtrl().GetNextItem(hChildItem, TVGN_NEXT);
p_clusterDataItem = ( ClusterData * ) leftView->GetTreeCtrl().GetItemData( hChildItem ); if( p_clusterDataItem->cp.cIP == parameters->clusterData->cp.cIP ) { // the cluster is found.
// get the exact host. Change icon of this host.
hChildItem = leftView->GetTreeCtrl().GetChildItem( hChildItem ); while( hChildItem != NULL ) { hNextItem = leftView->GetTreeCtrl().GetNextItem(hChildItem, TVGN_NEXT); _bstr_t* machineName = (_bstr_t *) leftView->GetTreeCtrl().GetItemData( hChildItem ); if( *( machineName ) == *(parameters->machineName) ) { // found machine to change icon of.
leftView->GetTreeCtrl().SetItemImage( hChildItem, 5, 5 ); goto outofloop; }
hChildItem = hNextItem; } } hChildItem = hNextItem; } }
outofloop:
// loop for around let us say 1 minute.
// enable the icon.
Sleep( 10000 );
leftView->GetTreeCtrl().SetItemImage( hChildItem, 2, 2 );
return 0; }
|