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.

398 lines
12 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CClusSvc.cpp
  7. //
  8. // Description:
  9. // Contains the definition of the CClusSvc class.
  10. //
  11. // Maintained By:
  12. // Vij Vasu (Vvasu) 08-MAR-2000
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. //////////////////////////////////////////////////////////////////////////////
  16. // Include Files
  17. //////////////////////////////////////////////////////////////////////////////
  18. // The precompiled header.
  19. #include "pch.h"
  20. // The header for this file
  21. #include "CClusSvc.h"
  22. // For DwRemoveDirectory()
  23. #include "Common.h"
  24. // To set the failure actions of the cluster service.
  25. #include "clusrtl.h"
  26. //////////////////////////////////////////////////////////////////////////////
  27. // Macros
  28. //////////////////////////////////////////////////////////////////////////////
  29. // Name of the NodeId cluster service parameter registry value.
  30. #define CLUSSVC_NODEID_VALUE L"NodeId"
  31. //////////////////////////////////////////////////////////////////////////////
  32. //++
  33. //
  34. // CClusSvc::CClusSvc()
  35. //
  36. // Description:
  37. // Constructor of the CClusSvc class
  38. //
  39. // Arguments:
  40. // pbcaParentActionIn
  41. // Pointer to the base cluster action of which this action is a part.
  42. //
  43. // Return Value:
  44. // None.
  45. //
  46. // Exceptions Thrown:
  47. // CAssert
  48. // If the parameters are incorrect.
  49. //
  50. // Any exceptions thrown by underlying functions
  51. //
  52. //--
  53. //////////////////////////////////////////////////////////////////////////////
  54. CClusSvc::CClusSvc(
  55. CBaseClusterAction * pbcaParentActionIn
  56. )
  57. : m_cservClusSvc( CLUSTER_SERVICE_NAME )
  58. , m_pbcaParentAction( pbcaParentActionIn )
  59. {
  60. BCATraceScope( "" );
  61. if ( m_pbcaParentAction == NULL)
  62. {
  63. BCATraceMsg( "Pointers to the parent action is NULL. Throwing exception." );
  64. THROW_ASSERT(
  65. E_INVALIDARG
  66. , "CClusSvc::CClusSvc() => Required input pointer in NULL"
  67. );
  68. } // if: the parent action pointer is NULL
  69. } //*** CClusSvc::CClusSvc()
  70. //////////////////////////////////////////////////////////////////////////////
  71. //++
  72. //
  73. // CClusSvc::~CClusSvc( void )
  74. //
  75. // Description:
  76. // Destructor of the CClusSvc class.
  77. //
  78. // Arguments:
  79. // None.
  80. //
  81. // Return Value:
  82. // None.
  83. //
  84. // Exceptions Thrown:
  85. // Any exceptions thrown by underlying functions
  86. //
  87. //--
  88. //////////////////////////////////////////////////////////////////////////////
  89. CClusSvc::~CClusSvc( void )
  90. {
  91. BCATraceScope( "" );
  92. } //*** CClusSvc::~CClusSvc()
  93. //////////////////////////////////////////////////////////////////////////////
  94. //++
  95. //
  96. // void
  97. // CClusSvc::ConfigureService()
  98. //
  99. // Description:
  100. // Create the service, set the failure actions and the service account.
  101. // Then start the service.
  102. //
  103. // Arguments:
  104. // pszClusterDomainAccountNameIn
  105. // pszClusterAccountPwdIn
  106. // Information about the account to be used as the cluster service
  107. // account.
  108. //
  109. // pszNodeIdString
  110. // String containing the Id of this node.
  111. //
  112. // Return Value:
  113. // None.
  114. //
  115. // Exceptions Thrown:
  116. // CRuntimeError
  117. // If any of the APIs fail.
  118. //
  119. // Any that are thrown by the underlying functions.
  120. //
  121. //--
  122. //////////////////////////////////////////////////////////////////////////////
  123. void
  124. CClusSvc::ConfigureService(
  125. const WCHAR * pszClusterDomainAccountNameIn
  126. , const WCHAR * pszClusterAccountPwdIn
  127. , const WCHAR * pszNodeIdStringIn
  128. , bool fIsVersionCheckingDisabledIn
  129. )
  130. {
  131. BCATraceScope( "" );
  132. DWORD dwError = ERROR_SUCCESS;
  133. CStatusReport srCreatingClusSvc(
  134. PbcaGetParent()->PBcaiGetInterfacePointer()
  135. , TASKID_Major_Configure_Cluster_Services
  136. , TASKID_Minor_Creating_Cluster_Service
  137. , 0, 2
  138. , IDS_TASK_CREATING_CLUSSVC
  139. );
  140. LogMsg( "Configuring the Cluster service." );
  141. // Send the next step of this status report.
  142. srCreatingClusSvc.SendNextStep( S_OK );
  143. // Create the cluster service.
  144. m_cservClusSvc.Create( m_pbcaParentAction->HGetMainInfFileHandle() );
  145. do
  146. {
  147. LogMsg( "Setting the Cluster service account information." );
  148. // Open a smart handle to the cluster service.
  149. SmartSCMHandle sscmhClusSvcHandle(
  150. OpenService(
  151. m_pbcaParentAction->HGetSCMHandle()
  152. , CLUSTER_SERVICE_NAME
  153. , SERVICE_CHANGE_CONFIG
  154. )
  155. );
  156. if ( sscmhClusSvcHandle.FIsInvalid() )
  157. {
  158. dwError = TW32( GetLastError() );
  159. BCATraceMsg( "OpenService() failed." );
  160. break;
  161. } // if: we could not open a handle to the cluster service.
  162. //
  163. // Set the service account information.
  164. //
  165. {
  166. if (
  167. ChangeServiceConfig(
  168. sscmhClusSvcHandle
  169. , SERVICE_NO_CHANGE
  170. , SERVICE_NO_CHANGE
  171. , SERVICE_NO_CHANGE
  172. , NULL
  173. , NULL
  174. , NULL
  175. , NULL
  176. , pszClusterDomainAccountNameIn
  177. , pszClusterAccountPwdIn
  178. , NULL
  179. )
  180. == FALSE
  181. )
  182. {
  183. dwError = TW32( GetLastError() );
  184. BCATraceMsg1(
  185. "ChangeServiceConfig() failed. Account = '%ws'."
  186. , pszClusterDomainAccountNameIn
  187. );
  188. break;
  189. } // if: we could not set the account information.
  190. }
  191. LogMsg( "Setting the Cluster service failure actions." );
  192. // Set the failure actions of the cluster service service.
  193. dwError = TW32( ClRtlSetSCMFailureActions( NULL ) );
  194. if ( dwError != ERROR_SUCCESS )
  195. {
  196. BCATraceMsg( "ClRtlSetSCMFailureActions() failed." );
  197. break;
  198. } // if: the service failure actions couldn't be set
  199. LogMsg( "Setting the Cluster service parameters." );
  200. // Send the next step of this status report.
  201. srCreatingClusSvc.SendNextStep( S_OK );
  202. {
  203. CRegistryKey rkClusSvcParams;
  204. // Open the parameters key or create it if it does not exist.
  205. rkClusSvcParams.CreateKey(
  206. HKEY_LOCAL_MACHINE
  207. , CLUSREG_KEYNAME_CLUSSVC_PARAMETERS
  208. , KEY_WRITE
  209. );
  210. // Set the NodeId string.
  211. rkClusSvcParams.SetValue(
  212. CLUSSVC_NODEID_VALUE
  213. , REG_SZ
  214. , reinterpret_cast< const BYTE * >( pszNodeIdStringIn )
  215. , ( wcslen( pszNodeIdStringIn ) + 1 ) * sizeof( *pszNodeIdStringIn )
  216. );
  217. // If version checking has been disabled, set a flag in the service parameters
  218. // to indicate this.
  219. if ( fIsVersionCheckingDisabledIn )
  220. {
  221. DWORD dwNoVersionCheck = 1;
  222. rkClusSvcParams.SetValue(
  223. CLUSREG_NAME_SVC_PARAM_NOVER_CHECK
  224. , REG_DWORD
  225. , reinterpret_cast< const BYTE * >( &dwNoVersionCheck )
  226. , sizeof( dwNoVersionCheck )
  227. );
  228. BCATraceMsg( "Cluster version checking has been disabled on this computer." );
  229. LogMsg( "Cluster version checking has been disabled on this computer." );
  230. } // if: version checking has been disabled
  231. }
  232. //
  233. // Set the cluster installation state.
  234. //
  235. if ( ClRtlSetClusterInstallState( eClusterInstallStateConfigured ) == FALSE )
  236. {
  237. dwError = TW32( GetLastError() );
  238. LogMsg( "Could not set the cluster installation state." );
  239. BCATraceMsg( "Could not set the cluster installation state. Throwing exception." );
  240. break;
  241. } // ClRtlSetClusterInstallState() failed.
  242. }
  243. while( false ); // dummy do-while loop to avoid gotos
  244. if ( dwError != ERROR_SUCCESS )
  245. {
  246. LogMsg( "Error %#08x occurred trying configure the ClusSvc service.", dwError );
  247. BCATraceMsg1( "Error %#08x occurred trying configure the ClusSvc service. Throwing exception.", dwError );
  248. THROW_RUNTIME_ERROR(
  249. HRESULT_FROM_WIN32( dwError )
  250. , IDS_ERROR_CLUSSVC_CONFIG
  251. );
  252. } // if; there was an error getting the handle.
  253. // Send the next step of this status report.
  254. srCreatingClusSvc.SendNextStep( S_OK );
  255. {
  256. UINT cQueryCount = 200;
  257. CStatusReport srStartingClusSvc(
  258. PbcaGetParent()->PBcaiGetInterfacePointer()
  259. , TASKID_Major_Configure_Cluster_Services
  260. , TASKID_Minor_Starting_Cluster_Service
  261. , 0, cQueryCount + 2 // we will send at most cQueryCount reports while waiting for the service to start (the two extra sends are below)
  262. , IDS_TASK_STARTING_CLUSSVC
  263. );
  264. // Send the next step of this status report.
  265. srStartingClusSvc.SendNextStep( S_OK );
  266. // Start the service.
  267. m_cservClusSvc.Start(
  268. m_pbcaParentAction->HGetSCMHandle()
  269. , true // wait for the service to start
  270. , 1500 // wait 1.5 seconds between queries for status.
  271. , cQueryCount // query cQueryCount times
  272. , &srStartingClusSvc // status report to be sent while waiting for the service to start
  273. );
  274. // Send the last step of this status report.
  275. srStartingClusSvc.SendLastStep( S_OK );
  276. }
  277. } //*** CClusSvc::ConfigureService()
  278. //////////////////////////////////////////////////////////////////////////////
  279. //++
  280. //
  281. // void
  282. // CClusSvc::CleanupService( void )
  283. //
  284. // Description:
  285. // Stop, cleanup and remove the service.
  286. //
  287. // Arguments:
  288. // None.
  289. //
  290. // Return Value:
  291. // None.
  292. //
  293. // Exceptions Thrown:
  294. // Any that are thrown by the underlying functions.
  295. //
  296. //--
  297. //////////////////////////////////////////////////////////////////////////////
  298. void
  299. CClusSvc::CleanupService( void )
  300. {
  301. BCATraceScope( "" );
  302. LogMsg( "Trying to stop the Cluster Service." );
  303. // Stop the service.
  304. m_cservClusSvc.Stop(
  305. m_pbcaParentAction->HGetSCMHandle()
  306. , 5000 // wait 5 seconds between queries for status.
  307. , 60 // query 60 times ( 5 minutes )
  308. );
  309. //
  310. // Restore the cluster installation state.
  311. //
  312. if ( ClRtlSetClusterInstallState( eClusterInstallStateFilesCopied ) == FALSE )
  313. {
  314. DWORD dwError = GetLastError();
  315. LogMsg( "Could not set the cluster installation state." );
  316. BCATraceMsg( "Could not set the cluster installation state. Throwing exception." );
  317. THROW_RUNTIME_ERROR(
  318. HRESULT_FROM_WIN32( dwError )
  319. , IDS_ERROR_SETTING_INSTALL_STATE
  320. );
  321. } // ClRtlSetClusterInstallState() failed.
  322. LogMsg( "Cleaning up Cluster Service." );
  323. m_cservClusSvc.Cleanup( m_pbcaParentAction->HGetMainInfFileHandle() );
  324. // Cleanup the local quorum directory.
  325. {
  326. DWORD dwError = ERROR_SUCCESS;
  327. const WCHAR * pcszQuorumDir = m_pbcaParentAction->RStrGetLocalQuorumDirectory().PszData();
  328. dwError = TW32( DwRemoveDirectory( pcszQuorumDir ) );
  329. if ( dwError != ERROR_SUCCESS )
  330. {
  331. BCATraceMsg2( "The local quorum directory '%s' cannot be removed. Non-fatal error %#x occurred.\n", pcszQuorumDir, dwError );
  332. LogMsg( "The local quorum directory '%s' cannot be removed. Non-fatal error %#x occurred.\n", pcszQuorumDir, dwError );
  333. } // if: we could not remove the local quorum directory
  334. }
  335. } //*** CClusSvc::CleanupService()