Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

790 lines
20 KiB

  1. // Copyright (c) Microsoft. All rights reserved.
  2. //
  3. // This is unpublished source code of Microsoft.
  4. // The copyright notice above does not evidence any
  5. // actual or intended publication of such source code.
  6. // OneLiner : Implementation of MNLBHost
  7. // DevUnit : wlbstest
  8. // Author : Murtaza Hakim
  9. // include files
  10. #include "MNLBHost.h"
  11. #include "MNLBCluster.h"
  12. #include "MNLBExe.h"
  13. #include "MNLBPortRule.h"
  14. #include "MTrace.h"
  15. #include "WTokens.h"
  16. #include "wlbsctrl.h"
  17. #include "Common.h"
  18. #include <iostream>
  19. using namespace std;
  20. // constructor
  21. //
  22. MNLBHost::MNLBHost( _bstr_t cip,
  23. int hID )
  24. :
  25. clusterIP( cip ),
  26. hostID( hID ),
  27. connectedToAny( false ),
  28. p_machine( NULL ),
  29. p_host( NULL )
  30. {
  31. MTrace* trace = MTrace::Instance();
  32. MTrace::TraceLevel prevLevel = trace->GetLevel();
  33. try
  34. {
  35. trace->SetLevel( MTrace::NO_TRACE );
  36. connectToAnyHost();
  37. trace->SetLevel( prevLevel );
  38. }
  39. catch( _com_error e )
  40. {
  41. TRACE(MTrace::INFO, L"connection using clusterip has failed\n" );
  42. trace->SetLevel( prevLevel );
  43. connectToExactHost();
  44. }
  45. TRACE(MTrace::INFO, L"mhost constructor\n" );
  46. }
  47. // default constructor.
  48. //
  49. // note that default constructor is purposely left undefined.
  50. // NO one should be using it. It is declared just for vector class usage.
  51. // copy constructor
  52. //
  53. MNLBHost::MNLBHost(const MNLBHost& mhost)
  54. : clusterIP( mhost.clusterIP ),
  55. hostID( mhost.hostID ),
  56. hostIP( mhost.hostIP ),
  57. connectedToAny( mhost.connectedToAny )
  58. {
  59. p_machine = auto_ptr<MWmiObject>(new MWmiObject( *mhost.p_machine ));
  60. p_host = auto_ptr<MWmiInstance>( new MWmiInstance( *mhost.p_host ));
  61. TRACE(MTrace::INFO, L"mhost copy constructor\n" );
  62. }
  63. // assignment operator
  64. //
  65. MNLBHost&
  66. MNLBHost::operator=( const MNLBHost& rhs )
  67. {
  68. clusterIP = rhs.clusterIP;
  69. hostID = rhs.hostID;
  70. hostIP = rhs.hostIP;
  71. connectedToAny = rhs.connectedToAny;
  72. p_machine = auto_ptr<MWmiObject>(new MWmiObject( *rhs.p_machine ));
  73. p_host = auto_ptr<MWmiInstance>( new MWmiInstance( *rhs.p_host ));
  74. TRACE(MTrace::INFO, L"mhost assignment operator\n" );
  75. return *this;
  76. }
  77. // destructor
  78. //
  79. MNLBHost::~MNLBHost()
  80. {
  81. TRACE(MTrace::INFO, L"mhost destructor\n" );
  82. }
  83. // getHostProperties
  84. //
  85. // TODO: Code to find the nic name and nic guid remains to be added for win2k machines as well as whistler
  86. //
  87. MNLBHost::MNLBHost_Error
  88. MNLBHost::getHostProperties( HostProperties* hp )
  89. {
  90. if( connectedToAny == true )
  91. {
  92. TRACE(MTrace::INFO, L"retrying to connect to exact host\n" );
  93. connectToExactHost();
  94. }
  95. // get node properties
  96. //
  97. vector<MWmiParameter* > parameterStore;
  98. // the status code is to be got from the Node class.
  99. //
  100. MWmiParameter sc(L"StatusCode");
  101. parameterStore.push_back( &sc );
  102. p_host->getParameters( parameterStore );
  103. hp->hostStatus = long( sc.getValue() );
  104. parameterStore.erase( parameterStore.begin(), parameterStore.end() );
  105. MWmiParameter hip(L"DedicatedIPAddress");
  106. parameterStore.push_back( &hip );
  107. MWmiParameter hnm(L"DedicatedNetworkMask");
  108. parameterStore.push_back( &hnm );
  109. MWmiParameter hpr(L"HostPriority");
  110. parameterStore.push_back( &hpr );
  111. MWmiParameter cmos(L"ClusterModeOnStart");
  112. parameterStore.push_back( &cmos );
  113. MWmiParameter Server("__Server");
  114. parameterStore.push_back( &Server);
  115. // get instances of nodesetting class.
  116. //
  117. vector< MWmiInstance > instanceStore;
  118. wchar_t hostIDWChar[ Common::BUF_SIZE ];
  119. swprintf( hostIDWChar, L"%d", hostID );
  120. _bstr_t relPath = L"MicrosoftNLB_NodeSetting.Name=\"" + clusterIP + L":" + hostIDWChar + L"\"";
  121. p_machine->getSpecificInstance( L"MicrosoftNLB_NodeSetting",
  122. relPath,
  123. &instanceStore );
  124. instanceStore[0].getParameters( parameterStore );
  125. // set parameters to get for whistler
  126. // these properties only present in whistler.
  127. //
  128. vector<MWmiParameter* > parameterStoreWhistler;
  129. MWmiParameter AdapterGuid(L"AdapterGuid");
  130. parameterStoreWhistler.push_back( &AdapterGuid );
  131. // get whistler parameters
  132. bool machineIsWhistler = true;
  133. try
  134. {
  135. // this will fail on win2k
  136. // as adapterguid, igmpsupport etc are not present.
  137. instanceStore[0].getParameters( parameterStoreWhistler );
  138. }
  139. catch( _com_error e )
  140. {
  141. // maybe it was a win2k machine. This exception is expected, thus catch.
  142. // for better safety, need to find exact error code returned and then only do the
  143. // folllowing otherwise need to rethrow.
  144. //
  145. TRACE( MTrace::INFO, L"tried whistler operation on win2k, this is expected\n");
  146. machineIsWhistler = false;
  147. }
  148. hp->hIP = hip.getValue();
  149. hp->hSubnetMask = hnm.getValue();
  150. hp->hID = hpr.getValue();
  151. hp->initialClusterStateActive = cmos.getValue();
  152. hp->machineName = Server.getValue();
  153. if( machineIsWhistler == true )
  154. {
  155. Common::getNLBNicInfoForWhistler( hostIP,
  156. _bstr_t( AdapterGuid.getValue() ),
  157. hp->nicInfo );
  158. }
  159. else
  160. {
  161. Common::getNLBNicInfoForWin2k( hostIP,
  162. hp->nicInfo );
  163. }
  164. return MNLBHost_SUCCESS;
  165. }
  166. // getPortRulesLoadBalanced
  167. //
  168. MNLBHost::MNLBHost_Error
  169. MNLBHost::getPortRulesLoadBalanced( vector<MNLBPortRuleLoadBalanced>* portsLB )
  170. {
  171. vector<MWmiInstance> instanceStore;
  172. return getPortRulesLoadBalanced_private( portsLB,
  173. &instanceStore );
  174. }
  175. // getPortRulesLoadBalanced_private
  176. //
  177. MNLBHost::MNLBHost_Error
  178. MNLBHost::getPortRulesLoadBalanced_private( vector<MNLBPortRuleLoadBalanced>* portsLB,
  179. vector<MWmiInstance>* instances )
  180. {
  181. if( connectedToAny == true )
  182. {
  183. TRACE(MTrace::INFO, L"retrying to connect to exact host\n" );
  184. connectToExactHost();
  185. }
  186. // get port properties.
  187. //
  188. vector<MWmiParameter* > parameterStore;
  189. MWmiParameter sp(L"StartPort");
  190. parameterStore.push_back( &sp );
  191. MWmiParameter ep(L"EndPort");
  192. parameterStore.push_back( &ep );
  193. MWmiParameter p(L"Protocol");
  194. parameterStore.push_back( &p );
  195. MWmiParameter el(L"EqualLoad");
  196. parameterStore.push_back( &el );
  197. MWmiParameter lw(L"LoadWeight");
  198. parameterStore.push_back( &lw );
  199. MWmiParameter a(L"Affinity");
  200. parameterStore.push_back( &a );
  201. MWmiParameter name(L"Name");
  202. parameterStore.push_back( &name );
  203. MNLBPortRule::Affinity affinity;
  204. MNLBPortRule::Protocol trafficToHandle;
  205. p_machine->getInstances( L"MicrosoftNLB_PortRuleLoadBalanced",
  206. instances );
  207. WTokens tok;
  208. _bstr_t temp;
  209. vector<wstring> tokens;
  210. for( int i = 0; i < instances->size(); ++i )
  211. {
  212. (*instances)[i].getParameters( parameterStore );
  213. // check if this instance belongs to the cluster.
  214. temp = _bstr_t( name.getValue() );
  215. tok.init( wstring( temp ),
  216. L":" );
  217. tokens = tok.tokenize();
  218. if( _bstr_t( tokens[0].c_str() ) != clusterIP )
  219. {
  220. // this instance does not belong to this cluster.
  221. continue;
  222. }
  223. switch( long (p.getValue()) )
  224. {
  225. case 1:
  226. trafficToHandle = MNLBPortRule::tcp;
  227. break;
  228. case 2:
  229. trafficToHandle = MNLBPortRule::udp;
  230. break;
  231. case 3:
  232. trafficToHandle = MNLBPortRule::both;
  233. break;
  234. default:
  235. // bug.
  236. TRACE( MTrace::SEVERE_ERROR, "unidentified protocol\n");
  237. throw _com_error( WBEM_E_UNEXPECTED );
  238. break;
  239. }
  240. switch( long(a.getValue()) )
  241. {
  242. case 0:
  243. affinity = MNLBPortRule::none;
  244. break;
  245. case 1:
  246. affinity = MNLBPortRule::single;
  247. break;
  248. case 2:
  249. affinity = MNLBPortRule::classC;
  250. break;
  251. default:
  252. // bug.
  253. TRACE( MTrace::SEVERE_ERROR, "unidentified affinity\n");
  254. throw _com_error( WBEM_E_UNEXPECTED );
  255. break;
  256. }
  257. portsLB->push_back( MNLBPortRuleLoadBalanced(long (sp.getValue()),
  258. long( ep.getValue()),
  259. trafficToHandle,
  260. bool( el.getValue()),
  261. long( lw.getValue()),
  262. affinity) );
  263. }
  264. return MNLBHost_SUCCESS;
  265. }
  266. // getPortRulesFailover
  267. //
  268. MNLBHost::MNLBHost_Error
  269. MNLBHost::getPortRulesFailover( vector<MNLBPortRuleFailover>* portsF )
  270. {
  271. vector<MWmiInstance> instanceStore;
  272. return getPortRulesFailover_private( portsF,
  273. &instanceStore );
  274. }
  275. // getPortRulesFailover_private
  276. //
  277. MNLBHost::MNLBHost_Error
  278. MNLBHost::getPortRulesFailover_private( vector<MNLBPortRuleFailover>* portsF,
  279. vector<MWmiInstance>* instances )
  280. {
  281. if( connectedToAny == true )
  282. {
  283. TRACE(MTrace::INFO, L"retrying to connect to exact host\n" );
  284. connectToExactHost();
  285. }
  286. // get port properties.
  287. //
  288. vector<MWmiParameter* > parameterStore;
  289. MWmiParameter sp(L"StartPort");
  290. parameterStore.push_back( &sp );
  291. MWmiParameter ep(L"EndPort");
  292. parameterStore.push_back( &ep );
  293. MWmiParameter p(L"Protocol");
  294. parameterStore.push_back( &p );
  295. MWmiParameter pr(L"Priority");
  296. parameterStore.push_back( &pr );
  297. MWmiParameter name(L"Name");
  298. parameterStore.push_back( &name );
  299. MNLBPortRule::Protocol trafficToHandle;
  300. p_machine->getInstances( L"MicrosoftNLB_PortRuleFailover",
  301. instances );
  302. WTokens tok;
  303. _bstr_t temp;
  304. vector<wstring> tokens;
  305. for( int i = 0; i < instances->size(); ++i )
  306. {
  307. (*instances)[i].getParameters( parameterStore );
  308. // check if this instance belongs to the cluster.
  309. temp = _bstr_t( name.getValue() );
  310. tok.init( wstring( temp ),
  311. L":" );
  312. tokens = tok.tokenize();
  313. if( _bstr_t( tokens[0].c_str() ) != clusterIP )
  314. {
  315. // this instance does not belong to this cluster.
  316. continue;
  317. }
  318. switch( long (p.getValue()) )
  319. {
  320. case 1:
  321. trafficToHandle = MNLBPortRule::tcp;
  322. break;
  323. case 2:
  324. trafficToHandle = MNLBPortRule::udp;
  325. break;
  326. case 3:
  327. trafficToHandle = MNLBPortRule::both;
  328. break;
  329. default:
  330. // bug.
  331. TRACE( MTrace::SEVERE_ERROR, "unidentified protocol\n");
  332. throw _com_error( WBEM_E_UNEXPECTED );
  333. break;
  334. }
  335. portsF->push_back( MNLBPortRuleFailover(long (sp.getValue()),
  336. long( ep.getValue()),
  337. trafficToHandle,
  338. long( pr.getValue()) )
  339. );
  340. }
  341. return MNLBHost_SUCCESS;
  342. }
  343. // getPortRulesDisabled
  344. //
  345. MNLBHost::MNLBHost_Error
  346. MNLBHost::getPortRulesDisabled( vector<MNLBPortRuleDisabled>* portsD )
  347. {
  348. vector<MWmiInstance> instanceStore;
  349. return getPortRulesDisabled_private( portsD,
  350. &instanceStore );
  351. }
  352. // getPortRulesDisabled_private
  353. //
  354. MNLBHost::MNLBHost_Error
  355. MNLBHost::getPortRulesDisabled_private( vector<MNLBPortRuleDisabled>* portsD,
  356. vector<MWmiInstance>* instances )
  357. {
  358. if( connectedToAny == true )
  359. {
  360. TRACE(MTrace::INFO, L"retrying to connect to exact host\n" );
  361. connectToExactHost();
  362. }
  363. // get port properties.
  364. //
  365. vector<MWmiParameter* > parameterStore;
  366. MWmiParameter sp(L"StartPort");
  367. parameterStore.push_back( &sp );
  368. MWmiParameter ep(L"EndPort");
  369. parameterStore.push_back( &ep );
  370. MWmiParameter p(L"Protocol");
  371. parameterStore.push_back( &p );
  372. MWmiParameter name(L"Name");
  373. parameterStore.push_back( &name );
  374. MNLBPortRule::Protocol trafficToHandle;
  375. p_machine->getInstances( L"MicrosoftNLB_PortRuleDisabled",
  376. instances );
  377. WTokens tok;
  378. _bstr_t temp;
  379. vector<wstring> tokens;
  380. for( int i = 0; i < instances->size(); ++i )
  381. {
  382. (*instances)[i].getParameters( parameterStore );
  383. // check if this instance belongs to the cluster.
  384. temp = _bstr_t( name.getValue() );
  385. tok.init( wstring( temp ),
  386. L":" );
  387. tokens = tok.tokenize();
  388. if( _bstr_t( tokens[0].c_str() ) != clusterIP )
  389. {
  390. // this instance does not belong to this cluster.
  391. continue;
  392. }
  393. switch( long (p.getValue()) )
  394. {
  395. case 1:
  396. trafficToHandle = MNLBPortRule::tcp;
  397. break;
  398. case 2:
  399. trafficToHandle = MNLBPortRule::udp;
  400. break;
  401. case 3:
  402. trafficToHandle = MNLBPortRule::both;
  403. break;
  404. default:
  405. // bug.
  406. TRACE( MTrace::SEVERE_ERROR, "unidentified protocol\n");
  407. throw _com_error( WBEM_E_UNEXPECTED );
  408. break;
  409. }
  410. portsD->push_back( MNLBPortRuleDisabled( long (sp.getValue() ),
  411. long( ep.getValue() ),
  412. trafficToHandle ) );
  413. }
  414. return MNLBHost_SUCCESS;
  415. }
  416. // getCluster
  417. //
  418. MNLBHost::MNLBHost_Error
  419. MNLBHost::getCluster( MNLBCluster* cluster)
  420. {
  421. vector<MWmiParameter* > parameterStore;
  422. MWmiParameter Name(L"Name");
  423. parameterStore.push_back( &Name );
  424. WTokens tok;
  425. _bstr_t temp;
  426. vector<wstring> tokens;
  427. p_host->getParameters( parameterStore );
  428. // getting cluster ip from name of clusterip:hostid
  429. //
  430. temp = _bstr_t( Name.getValue() );
  431. tok.init( wstring( temp ),
  432. L":" );
  433. tokens = tok.tokenize();
  434. *cluster = MNLBCluster( tokens[0].c_str() );
  435. return MNLBHost_SUCCESS;
  436. }
  437. // connectToAnyHost
  438. //
  439. MNLBHost::MNLBHost_Error
  440. MNLBHost::connectToAnyHost()
  441. {
  442. vector< MWmiInstance > instanceStore;
  443. _bstr_t relPath;
  444. wchar_t hostIDWChar[ Common::BUF_SIZE ];
  445. swprintf( hostIDWChar, L"%d", hostID );
  446. p_machine = auto_ptr<MWmiObject>( new MWmiObject( clusterIP,
  447. L"root\\microsoftnlb",
  448. L"Administrator",
  449. L"") );
  450. relPath = L"MicrosoftNLB_Node.Name=\"" + clusterIP + ":" + hostIDWChar + L"\"";
  451. p_machine->getSpecificInstance( L"MicrosoftNLB_Node",
  452. relPath,
  453. &instanceStore );
  454. p_host = auto_ptr<MWmiInstance>( new MWmiInstance( instanceStore[0] ) );
  455. connectedToAny = true;
  456. return MNLBHost_SUCCESS;
  457. }
  458. // connectToExactHost
  459. //
  460. MNLBHost::MNLBHost_Error
  461. MNLBHost::connectToExactHost()
  462. {
  463. wchar_t hostIDWChar[ Common::BUF_SIZE ];
  464. swprintf( hostIDWChar, L"%d", hostID );
  465. //
  466. getHostIP();
  467. // check if host ip is zero. If so we cannot proceed.
  468. if( hostIP == _bstr_t( L"0.0.0.0" ) )
  469. {
  470. TRACE( MTrace::SEVERE_ERROR, "dedicated ip of this host is 0.0.0.0. This is not allowed. \n");
  471. throw _com_error( WBEM_E_INVALID_PROPERTY );
  472. }
  473. // connect to wmi object on host.
  474. //
  475. p_machine = auto_ptr<MWmiObject> ( new MWmiObject( hostIP,
  476. L"root\\microsoftnlb",
  477. L"Administrator",
  478. L"") );
  479. // get instances of node.
  480. //
  481. _bstr_t relPath = L"MicrosoftNLB_Node.Name=\"" + clusterIP + ":" + hostIDWChar + L"\"";
  482. vector< MWmiInstance > instanceStore;
  483. p_machine->getSpecificInstance( L"MicrosoftNLB_Node",
  484. relPath,
  485. &instanceStore );
  486. p_host = auto_ptr<MWmiInstance>( new MWmiInstance( instanceStore[0] ) );
  487. // set flag to indicate that we have connected to the exact host.
  488. connectedToAny = false;
  489. return MNLBHost_SUCCESS;
  490. }
  491. // getHostIP
  492. //
  493. MNLBHost::MNLBHost_Error
  494. MNLBHost::getHostIP()
  495. {
  496. vector<HostProperties> hostPropertiesStore;
  497. // get all hosts participating in cluster.
  498. DWORD ret = Common::getHostsInCluster( clusterIP, &hostPropertiesStore );
  499. if( hostPropertiesStore.size() == 0 )
  500. {
  501. // no hosts are in this cluster. Cannot proceed reliably.
  502. wstring errString;
  503. errString = L"cluster " + wstring( clusterIP ) + L" reported as having no hosts. Maybe cluster ip is wrong, or remote control is turned off\n";
  504. TRACE( MTrace::SEVERE_ERROR, errString );
  505. throw _com_error(WBEM_E_NOT_FOUND );
  506. }
  507. bool hostFound = false;
  508. for( int i = 0; i < hostPropertiesStore.size(); ++i )
  509. {
  510. if( hostPropertiesStore[i].hID == hostID )
  511. {
  512. hostIP = hostPropertiesStore[i].hIP;
  513. hostFound = true;
  514. break;
  515. }
  516. }
  517. if( hostFound == false )
  518. {
  519. wstring errString;
  520. errString = L"cluster " + wstring( clusterIP ) + L" reported as having no host with specified host id\n";
  521. TRACE( MTrace::SEVERE_ERROR, errString );
  522. throw _com_error( WBEM_E_NOT_FOUND );
  523. }
  524. return MNLBHost_SUCCESS;
  525. }
  526. // start
  527. //
  528. MNLBHost::MNLBHost_Error
  529. MNLBHost::start( unsigned long* retVal )
  530. {
  531. MNLBExe::start( *p_host, retVal );
  532. return MNLBHost_SUCCESS;
  533. }
  534. // stop
  535. //
  536. MNLBHost::MNLBHost_Error
  537. MNLBHost::stop( unsigned long* retVal )
  538. {
  539. MNLBExe::stop( *p_host, retVal );
  540. return MNLBHost_SUCCESS;
  541. }
  542. // resume
  543. //
  544. MNLBHost::MNLBHost_Error
  545. MNLBHost::resume( unsigned long* retVal )
  546. {
  547. MNLBExe::resume( *p_host, retVal );
  548. return MNLBHost_SUCCESS;
  549. }
  550. // suspend
  551. //
  552. MNLBHost::MNLBHost_Error
  553. MNLBHost::suspend( unsigned long* retVal )
  554. {
  555. MNLBExe::suspend( *p_host, retVal );
  556. return MNLBHost_SUCCESS;
  557. }
  558. // drainstop
  559. //
  560. MNLBHost::MNLBHost_Error
  561. MNLBHost::drainstop( unsigned long* retVal )
  562. {
  563. MNLBExe::drainstop( *p_host, retVal );
  564. return MNLBHost_SUCCESS;
  565. }
  566. // enable
  567. //
  568. MNLBHost::MNLBHost_Error
  569. MNLBHost::enable( unsigned long* retVal, unsigned long portToAffect )
  570. {
  571. MNLBExe::enable( *p_host, retVal, portToAffect );
  572. return MNLBHost_SUCCESS;
  573. }
  574. // disable
  575. //
  576. MNLBHost::MNLBHost_Error
  577. MNLBHost::disable( unsigned long* retVal, unsigned long portToAffect )
  578. {
  579. MNLBExe::disable( *p_host, retVal, portToAffect );
  580. return MNLBHost_SUCCESS;
  581. }
  582. // drain
  583. //
  584. MNLBHost::MNLBHost_Error
  585. MNLBHost::drain( unsigned long* retVal, unsigned long portToAffect )
  586. {
  587. MNLBExe::drain( *p_host, retVal, portToAffect );
  588. return MNLBHost_SUCCESS;
  589. }
  590. // refreshConnection
  591. //
  592. MNLBHost::MNLBHost_Error
  593. MNLBHost::refreshConnection()
  594. {
  595. return connectToExactHost();
  596. }