Leaked source code of windows server 2003
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.

578 lines
12 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. nodeapi.c
  5. Abstract:
  6. Public interfaces for managing cluster nodes.
  7. Author:
  8. John Vert (jvert) 15-Jan-1996
  9. Revision History:
  10. --*/
  11. #include "clusapip.h"
  12. //
  13. // Cluster Node Management Routines.
  14. //
  15. HNODE
  16. WINAPI
  17. OpenClusterNode(
  18. IN HCLUSTER hCluster,
  19. IN LPCWSTR lpszNodeName
  20. )
  21. /*++
  22. Routine Description:
  23. Opens an individual node in the cluster.
  24. Arguments:
  25. hCluster - Supplies a cluster handle returned from OpenCluster.
  26. lpszNodeName - Supplies the name of the individual node to open.
  27. Return Value:
  28. non-NULL - returns an open handle to the specified cluster.
  29. NULL - The operation failed. Extended error status is available
  30. using GetLastError()
  31. --*/
  32. {
  33. PCLUSTER Cluster;
  34. PCNODE Node;
  35. error_status_t Status = ERROR_SUCCESS;
  36. Cluster = (PCLUSTER)hCluster;
  37. Node = LocalAlloc(LMEM_FIXED, sizeof(CNODE));
  38. if (Node == NULL) {
  39. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  40. return(NULL);
  41. }
  42. Node->Name = LocalAlloc(LMEM_FIXED, (lstrlenW(lpszNodeName)+1)*sizeof(WCHAR));
  43. if (Node->Name == NULL) {
  44. LocalFree(Node);
  45. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  46. return(NULL);
  47. }
  48. lstrcpyW(Node->Name, lpszNodeName);
  49. Node->Cluster = Cluster;
  50. InitializeListHead(&Node->NotifyList);
  51. WRAP_NULL(Node->hNode,
  52. (ApiOpenNode(Cluster->RpcBinding,
  53. lpszNodeName,
  54. &Status)),
  55. &Status,
  56. Cluster);
  57. if ((Node->hNode == NULL) || (Status != ERROR_SUCCESS)) {
  58. LocalFree(Node->Name);
  59. LocalFree(Node);
  60. SetLastError(Status);
  61. return(NULL);
  62. }
  63. //
  64. // Link newly opened Node onto the cluster structure.
  65. //
  66. EnterCriticalSection(&Cluster->Lock);
  67. InsertHeadList(&Cluster->NodeList, &Node->ListEntry);
  68. LeaveCriticalSection(&Cluster->Lock);
  69. return((HNODE)Node);
  70. }
  71. BOOL
  72. WINAPI
  73. CloseClusterNode(
  74. IN HNODE hNode
  75. )
  76. /*++
  77. Routine Description:
  78. Closes a handle to an individual cluster node
  79. Arguments:
  80. hNode - Supplies the cluster node to be closed
  81. Return Value:
  82. TRUE - The operation was successful.
  83. FALSE - The operation failed. Extended error status is available
  84. using GetLastError()
  85. --*/
  86. {
  87. PCNODE Node;
  88. PCLUSTER Cluster;
  89. Node = (PCNODE)hNode;
  90. Cluster = (PCLUSTER)Node->Cluster;
  91. //
  92. // Unlink node from cluster list.
  93. //
  94. EnterCriticalSection(&Cluster->Lock);
  95. RemoveEntryList(&Node->ListEntry);
  96. //
  97. // Remove any notifications posted against this resource.
  98. //
  99. RundownNotifyEvents(&Node->NotifyList, Node->Name);
  100. //if the cluster is dead and the reconnect has failed,
  101. //the Node->hNode might be NULL if s_apiopennode for
  102. //this node failed on a reconnect
  103. //the cluster may be dead and hNode may be non null, say
  104. //if reconnectnodes succeeded but the reconnectnetworks
  105. //failed
  106. // At reconnect, the old context is saved in the obsolete
  107. // list for deletion when the cluster handle is closed
  108. if ((Cluster->Flags & CLUS_DEAD) && (Node->hNode)) {
  109. RpcSmDestroyClientContext(&Node->hNode);
  110. LeaveCriticalSection(&Cluster->Lock);
  111. goto FnExit;
  112. }
  113. LeaveCriticalSection(&Cluster->Lock);
  114. //
  115. // Close RPC context handle
  116. //
  117. ApiCloseNode(&Node->hNode);
  118. FnExit:
  119. //
  120. // Free memory allocations
  121. //
  122. LocalFree(Node->Name);
  123. LocalFree(Node);
  124. //
  125. // Give the cluster a chance to clean up in case this
  126. // node was the only thing keeping it around.
  127. //
  128. CleanupCluster(Cluster);
  129. return(TRUE);
  130. }
  131. #undef GetCurrentClusterNodeId
  132. DWORD
  133. GetCurrentClusterNodeId(
  134. OUT LPWSTR lpszNodeId,
  135. IN OUT LPDWORD lpcchName
  136. )
  137. /*++
  138. Routine Description:
  139. Returns the node identifier of the current node. This function
  140. is only available on a node that is currently online and a member
  141. of a cluster.
  142. Arguments:
  143. lpszNodeId - Points to a buffer that receives the unique ID of the object,
  144. including the terminating null character.
  145. lpcchName - Points to a variable that specifies the size, in characters
  146. of the buffer pointed to by the lpszNodeId parameter. This size
  147. should include the terminating null character. When the function
  148. returns, the variable pointed to be lpcchName contains the number
  149. of characters stored in the buffer. The count returned does not
  150. include the terminating null character.
  151. Return Value:
  152. If the function succeeds, the return value is ERROR_SUCCESS.
  153. If the function fails, the return value is an error value.
  154. --*/
  155. {
  156. HCLUSTER Cluster;
  157. HNODE CurrentNode;
  158. DWORD Status;
  159. Cluster = OpenCluster(NULL);
  160. if (Cluster == NULL) {
  161. return(GetLastError());
  162. }
  163. CurrentNode = OpenClusterNode(Cluster,
  164. ((PCLUSTER)Cluster)->NodeName);
  165. if (CurrentNode != NULL) {
  166. Status = GetClusterNodeId(CurrentNode,
  167. lpszNodeId,
  168. lpcchName);
  169. CloseClusterNode(CurrentNode);
  170. }
  171. else
  172. {
  173. Status = GetLastError();
  174. }
  175. CloseCluster(Cluster);
  176. return(Status);
  177. }
  178. DWORD
  179. WINAPI
  180. GetClusterNodeId(
  181. IN HNODE hNode,
  182. OUT LPWSTR lpszNodeId,
  183. IN OUT LPDWORD lpcchName
  184. )
  185. /*++
  186. Routine Description:
  187. Returns the unique identifier of the specified node
  188. Arguments:
  189. hNode - Supplies the node whose unique ID is to be returned.
  190. lpszNodeId - Points to a buffer that receives the unique ID of the object,
  191. including the terminating null character.
  192. lpcchName - Points to a variable that specifies the size, in characters
  193. of the buffer pointed to by the lpszNodeId parameter. This size
  194. should include the terminating null character. When the function
  195. returns, the variable pointed to be lpcchName contains the number
  196. of characters stored in the buffer. The count returned does not
  197. include the terminating null character.
  198. Return Value:
  199. If the function succeeds, the return value is ERROR_SUCCESS.
  200. If the function fails, the return value is an error value.
  201. --*/
  202. {
  203. DWORD Status;
  204. DWORD Length;
  205. PCNODE Node = (PCNODE)hNode;
  206. LPWSTR Guid=NULL;
  207. if (Node == NULL) {
  208. return(GetCurrentClusterNodeId(lpszNodeId, lpcchName));
  209. }
  210. WRAP(Status,
  211. (ApiGetNodeId(Node->hNode,
  212. &Guid)),
  213. Node->Cluster);
  214. if (Status != ERROR_SUCCESS) {
  215. return(Status);
  216. }
  217. MylstrcpynW(lpszNodeId, Guid, *lpcchName);
  218. Length = lstrlenW(Guid);
  219. if (Length >= *lpcchName) {
  220. if (lpszNodeId == NULL) {
  221. Status = ERROR_SUCCESS;
  222. } else {
  223. Status = ERROR_MORE_DATA;
  224. }
  225. }
  226. *lpcchName = Length;
  227. MIDL_user_free(Guid);
  228. return(Status);
  229. }
  230. CLUSTER_NODE_STATE
  231. WINAPI
  232. GetClusterNodeState(
  233. IN HNODE hNode
  234. )
  235. /*++
  236. Routine Description:
  237. Returns the current state of a cluster node.
  238. Arguments:
  239. hNode - Supplies the cluster node whose current state is to be returned
  240. Return Value:
  241. The current state of the cluster node. Currently defined node states
  242. include:
  243. ClusterNodeUp
  244. ClusterNodeDown
  245. ClusterNodePaused
  246. --*/
  247. {
  248. DWORD Status;
  249. CLUSTER_NODE_STATE State;
  250. PCNODE Node = (PCNODE)hNode;
  251. WRAP(Status,
  252. (ApiGetNodeState(Node->hNode, (LPDWORD)&State)),
  253. Node->Cluster);
  254. if (Status == ERROR_SUCCESS) {
  255. return(State);
  256. } else {
  257. SetLastError(Status);
  258. return(ClusterNodeStateUnknown);
  259. }
  260. }
  261. DWORD
  262. WINAPI
  263. PauseClusterNode(
  264. IN HNODE hNode
  265. )
  266. /*++
  267. Routine Description:
  268. Requests that a node pauses its cluster activity.
  269. Arguments:
  270. hNode - Supplies a handle to the node to leave its cluster.
  271. Return Value:
  272. ERROR_SUCCESS if successful
  273. Win32 error code otherwise
  274. --*/
  275. {
  276. DWORD Status;
  277. PCNODE Node = (PCNODE)hNode;
  278. WRAP(Status,
  279. (ApiPauseNode(Node->hNode)),
  280. Node->Cluster);
  281. return(Status);
  282. }
  283. DWORD
  284. WINAPI
  285. ResumeClusterNode(
  286. IN HNODE hNode
  287. )
  288. /*++
  289. Routine Description:
  290. Requests that a node resume cluster activity, after it had been paused.
  291. Arguments:
  292. hNode - Supplies a handle to the node to resume its cluster activity.
  293. Return Value:
  294. ERROR_SUCCESS if successful
  295. Win32 error code otherwise
  296. --*/
  297. {
  298. DWORD Status;
  299. PCNODE Node = (PCNODE)hNode;
  300. WRAP(Status,
  301. (ApiResumeNode(Node->hNode)),
  302. Node->Cluster);
  303. return(Status);
  304. }
  305. DWORD
  306. WINAPI
  307. EvictClusterNode(
  308. IN HNODE hNode
  309. )
  310. /*++
  311. Routine Description:
  312. Evict the specified Node from the list of nodes in the permanent cluster
  313. database (registry).
  314. Arguments:
  315. hNode - Supplies a handle to the node to remove from the list of cluster
  316. nodes.
  317. Return Value:
  318. ERROR_SUCCESS if successful
  319. Win32 error code otherwise
  320. --*/
  321. {
  322. DWORD Status;
  323. PCNODE Node = (PCNODE)hNode;
  324. WRAP(Status,
  325. (ApiEvictNode(Node->hNode)),
  326. Node->Cluster);
  327. return(Status);
  328. }
  329. DWORD
  330. WINAPI
  331. EvictClusterNodeEx(
  332. IN HNODE hNode,
  333. IN DWORD dwTimeout,
  334. OUT HRESULT* phrCleanupStatus
  335. )
  336. /*++
  337. Routine Description:
  338. Evict the specified node from the list of nodes in the permanent cluster
  339. database (registry) and initate the cleanup(unconfiguration) process on the
  340. cluster node. Note that if the node is down, the clean up process will not
  341. occur. However, when the node comes up, clustering will detect that the
  342. node was supposed to be evicted and it will unconfigure itself.
  343. Arguments:
  344. IN HNODE hNode - Supplies a handle to the node to remove from the list of cluster
  345. nodes.
  346. IN DWORD dwTimeOut - Timeout in milliseconds for the cleanup(unconfiguration
  347. of clustering) to complete. If the cleanup doesnt complete
  348. in the given amount of time, the function will return.
  349. OUT phrCleanupStatus - The status of cleanup is returned.
  350. Return Value:
  351. Returns the status of the eviction and not of cleanup.
  352. ERROR_SUCCESS if successful
  353. ERROR_CLUSTER_EVICT_WITHOUT_CLEANUP if eviction succeeded but cleanup returned
  354. an error. The phrCleanupStatus param will contain more information about
  355. the cleanup error. (Usually this will be RPC_S_CALL_FAILED.)
  356. Win32 error code otherwise
  357. --*/
  358. {
  359. DWORD Status;
  360. PCNODE Node = (PCNODE)hNode;
  361. HRESULT hr = E_ABORT;
  362. WRAP(Status,
  363. (ApiEvictNode(Node->hNode)),
  364. Node->Cluster);
  365. if (Status != ERROR_SUCCESS) {
  366. goto FnExit;
  367. }
  368. //
  369. // Any error after this is not "fatal". The node has been evicted
  370. // but the cleanup may fail for numerous reasons.
  371. //
  372. hr = ClRtlAsyncCleanupNode(Node->Name, 0, dwTimeout);
  373. if (FAILED(hr)) {
  374. Status = ERROR_CLUSTER_EVICT_WITHOUT_CLEANUP;
  375. }
  376. FnExit:
  377. if (phrCleanupStatus != NULL) {
  378. *phrCleanupStatus = hr;
  379. }
  380. return(Status);
  381. } // EvictClusterNodeEx()
  382. HCLUSTER
  383. WINAPI
  384. GetClusterFromNode(
  385. IN HNODE hNode
  386. )
  387. /*++
  388. Routine Description:
  389. Returns the cluster handle from the associated node handle.
  390. Arguments:
  391. hNode - Supplies the node.
  392. Return Value:
  393. Handle to the cluster associated with the node handle.
  394. --*/
  395. {
  396. DWORD nStatus;
  397. PCNODE Node = (PCNODE)hNode;
  398. HCLUSTER hCluster = (HCLUSTER)Node->Cluster;
  399. nStatus = AddRefToClusterHandle( hCluster );
  400. if ( nStatus != ERROR_SUCCESS ) {
  401. SetLastError( nStatus );
  402. hCluster = NULL;
  403. }
  404. return( hCluster );
  405. } // GetClusterFromNode()