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.
2592 lines
64 KiB
2592 lines
64 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
recv.c
|
|
|
|
Abstract:
|
|
|
|
Cluster FM remote receive request routines.
|
|
|
|
Author:
|
|
|
|
Rod Gamache (rodga) 21-Mar-1996
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "fmp.h"
|
|
|
|
#define LOG_MODULE RECV
|
|
|
|
//
|
|
// Global data
|
|
//
|
|
|
|
extern BOOL FmpOkayToProceed;
|
|
|
|
//
|
|
// Local function prototypes
|
|
//
|
|
BOOL
|
|
FmpEnumMyGroups(
|
|
IN OUT PGROUP_ENUM *Enum,
|
|
IN LPDWORD Allocated,
|
|
IN PFM_GROUP Group,
|
|
IN LPCWSTR Id
|
|
);
|
|
|
|
BOOL
|
|
FmpEnumResources(
|
|
IN OUT PRESOURCE_ENUM *Enum,
|
|
IN LPDWORD Allocated,
|
|
IN PFM_RESOURCE Resource,
|
|
IN LPCWSTR Id
|
|
);
|
|
|
|
|
|
error_status_t
|
|
s_FmsOnlineGroupRequest(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR GroupId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Group Online Request from (THE) remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
GroupId - The Id of the Group to bring online.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_GROUP group;
|
|
DWORD status;
|
|
|
|
FmpMustBeOnline( );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsOnlineGroupRequest: To bring group '%1!ws!' online\n",
|
|
GroupId);
|
|
|
|
//
|
|
// Find the specified group.
|
|
//
|
|
|
|
group = OmReferenceObjectById( ObjectTypeGroup, GroupId );
|
|
|
|
if ( group == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsOnlineGroupRequest: Could not find Group %1!ws!\n",
|
|
GroupId);
|
|
return(ERROR_GROUP_NOT_FOUND);
|
|
}
|
|
|
|
//
|
|
// Only one of these requests per group at a time.
|
|
//
|
|
FmpAcquireLocalGroupLock( group );
|
|
|
|
|
|
//
|
|
// Now bring it online.
|
|
//
|
|
if ( group->OwnerNode == NmLocalNode ) {
|
|
//
|
|
// Set the Group's Current State.
|
|
//
|
|
FmpSetGroupPersistentState( group, ClusterGroupOnline );
|
|
|
|
status = FmpOnlineGroup( group, TRUE );
|
|
} else {
|
|
status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
}
|
|
|
|
FmpReleaseLocalGroupLock( group );
|
|
|
|
OmDereferenceObject( group );
|
|
|
|
return(status);
|
|
|
|
} // FmsOnlineGroupRequest
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsOfflineGroupRequest(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR GroupId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Group Offline Request from (THE) remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
GroupId - The Id of the Group to bring offline.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_GROUP group;
|
|
DWORD status;
|
|
|
|
FmpMustBeOnline( );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsOfflineGroupRequest: To take group '%1!ws!' offline\n",
|
|
GroupId);
|
|
|
|
//
|
|
// Find the specified group.
|
|
//
|
|
|
|
group = OmReferenceObjectById( ObjectTypeGroup, GroupId );
|
|
|
|
if ( group == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsOfflineGroupRequest: Could not find Group %1!ws!\n",
|
|
GroupId);
|
|
return(ERROR_GROUP_NOT_FOUND);
|
|
}
|
|
|
|
//
|
|
// Now take it offline if we are the owner.
|
|
//
|
|
if ( group->OwnerNode == NmLocalNode ) {
|
|
//
|
|
// Set the Group's Current State.
|
|
//
|
|
FmpSetGroupPersistentState( group, ClusterGroupOffline );
|
|
|
|
status = FmpOfflineGroup( group, FALSE, TRUE );
|
|
} else {
|
|
status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
}
|
|
|
|
OmDereferenceObject( group );
|
|
|
|
return(status);
|
|
|
|
} // FmsOfflineGroupRequest
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsMoveGroupRequest(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR GroupId,
|
|
IN LPCWSTR DestinationNode OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Group Move Request from (THE) remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
GroupId - The Id of the Group to move.
|
|
DestinationNode - The Id of the node to move the Group to.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_GROUP group;
|
|
PNM_NODE node = NULL;
|
|
DWORD status;
|
|
|
|
FmpMustBeOnline( );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsMoveGroupRequest: To move group '%1!ws!'\n",
|
|
GroupId);
|
|
|
|
//
|
|
//
|
|
// Find the specified group.
|
|
//
|
|
|
|
group = OmReferenceObjectById( ObjectTypeGroup, GroupId );
|
|
|
|
if ( group == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsMoveGroupRequest: Could not find Group %1!ws!\n",
|
|
GroupId);
|
|
return(ERROR_GROUP_NOT_FOUND);
|
|
}
|
|
|
|
//
|
|
// Find the specified destination node.
|
|
//
|
|
|
|
if ( ARGUMENT_PRESENT( DestinationNode ) ) {
|
|
node = OmReferenceObjectById( ObjectTypeNode, DestinationNode );
|
|
|
|
if ( node == NULL ) {
|
|
OmDereferenceObject( group );
|
|
ClRtlLogPrint(LOG_NOISE,"[FM] FmsMoveGroupRequest: Could not find Node %1!ws!\n", DestinationNode);
|
|
return(ERROR_HOST_NODE_NOT_AVAILABLE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make sure we are the owner of the Group.
|
|
//
|
|
FmpAcquireLocalGroupLock( group );
|
|
if ( group->OwnerNode == NmLocalNode ) {
|
|
status = FmpDoMoveGroup( group, node, TRUE );
|
|
} else {
|
|
status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
}
|
|
FmpReleaseLocalGroupLock( group );
|
|
|
|
OmDereferenceObject( group );
|
|
if ( node != NULL ) {
|
|
OmDereferenceObject( node );
|
|
}
|
|
|
|
return(status);
|
|
|
|
} // FmsMoveGroupRequest
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsTakeGroupRequest(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR GroupId,
|
|
IN PRESOURCE_ENUM ResourceList
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Take Group Request from (THE) remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
GroupId - The Id of the Group to take locally.
|
|
ResourceList - The list of resources and their states.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_GROUP group;
|
|
DWORD status = ERROR_SUCCESS;
|
|
|
|
//SS: removing this check from here
|
|
//FmpTakeGroupRequest does this check since if this call returns a failure,
|
|
//the intended owner needs to be reset to invalidnode to avoid inconsistencies
|
|
//FmpMustBeOnline( );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsTakeGroupRequest: To take group '%1!ws!'.\n",
|
|
GroupId );
|
|
|
|
//
|
|
//
|
|
// Find the specified group.
|
|
//
|
|
|
|
group = OmReferenceObjectById( ObjectTypeGroup, GroupId );
|
|
|
|
if ( group == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsTakeGroupRequest: Could not find Group %1!ws!\n",
|
|
GroupId);
|
|
if ( !FmpFMOnline ) {
|
|
return(ERROR_CLUSTER_NODE_NOT_READY);
|
|
}
|
|
return(ERROR_GROUP_NOT_FOUND);
|
|
}
|
|
|
|
status = FmpTakeGroupRequest(group, ResourceList);
|
|
OmDereferenceObject(group);
|
|
|
|
return(status);
|
|
|
|
} // FmsTakeGroupRequest
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsOnlineResourceRequest(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Resource Online Request from (THE) remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
ResourceId - The Id of the Resource to bring online.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE resource;
|
|
DWORD status;
|
|
|
|
FmpMustBeOnline( );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsOnlineResourceRequest: To bring resource '%1!ws!' online\n",
|
|
ResourceId);
|
|
|
|
//
|
|
// Find the specified resource.
|
|
//
|
|
resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
|
|
|
|
if ( resource == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsOnlineResourceRequest: Could not find Resource %1!ws!\n",
|
|
ResourceId);
|
|
return(ERROR_RESOURCE_NOT_FOUND);
|
|
}
|
|
|
|
FmpAcquireLocalResourceLock( resource );
|
|
|
|
if (!(resource->QuorumResource) &&
|
|
!FmpInPreferredList( resource->Group, resource->Group->OwnerNode, TRUE, resource ) ) {
|
|
status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
goto FnExit;
|
|
}
|
|
|
|
//
|
|
// Now bring it online.
|
|
//
|
|
CL_ASSERT( resource->Group != NULL );
|
|
if ( resource->Group->OwnerNode == NmLocalNode ) {
|
|
//
|
|
// This can only be invoked through the API, so force all
|
|
// resources online.
|
|
//
|
|
status = FmOnlineResource( resource );
|
|
} else {
|
|
status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
}
|
|
|
|
FnExit:
|
|
FmpReleaseLocalResourceLock( resource );
|
|
|
|
OmDereferenceObject( resource );
|
|
|
|
return(status);
|
|
|
|
} // FmsOnlineResourceRequest
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsOfflineResourceRequest(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Resource Offline Request from (THE) remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
ResourceId - The Id of the Resource to bring offline.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE resource;
|
|
DWORD status;
|
|
|
|
FmpMustBeOnline( );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsOfflineResourceRequest: To take resource '%1!ws!' offline\n",
|
|
ResourceId);
|
|
|
|
//
|
|
// Find the specified resource.
|
|
//
|
|
|
|
resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
|
|
|
|
if ( resource == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsOfflineResourceRequest: Could not find Resource %1!ws!\n",
|
|
ResourceId);
|
|
return(ERROR_RESOURCE_NOT_FOUND);
|
|
}
|
|
|
|
FmpAcquireLocalResourceLock(resource);
|
|
//
|
|
// Now take it offline if we are the owner.
|
|
//
|
|
CL_ASSERT( resource->Group != NULL );
|
|
if ( resource->Group->OwnerNode != NmLocalNode )
|
|
{
|
|
status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
goto FnExit;
|
|
}
|
|
//else handle it locally
|
|
status = FmOfflineResource( resource );
|
|
|
|
FnExit:
|
|
FmpReleaseLocalResourceLock(resource);
|
|
OmDereferenceObject( resource );
|
|
|
|
return(status);
|
|
|
|
} // FmsOfflineResourceRequest
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsChangeResourceNode(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceId,
|
|
IN LPCWSTR NodeId,
|
|
IN BOOL Add
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Resource change node request from a remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
ResourceId - The Id of the Resource to change a node.
|
|
NodeId - The node id of the node to add or remove.
|
|
Add - Indicates whether to add or remove the node.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE resource;
|
|
DWORD status;
|
|
|
|
FmpMustBeOnline( );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsChangeResourceNode: To %1!ws! node %2!ws! to/from resource '%3!ws!'.\n",
|
|
Add ? L"Add" : L"Remove",
|
|
NodeId,
|
|
ResourceId);
|
|
|
|
//
|
|
// Find the specified resource.
|
|
//
|
|
resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
|
|
|
|
if ( resource == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsChangeResourceNode: Could not find Resource %1!ws!\n",
|
|
ResourceId);
|
|
return(ERROR_RESOURCE_NOT_FOUND);
|
|
}
|
|
|
|
FmpAcquireLocalResourceLock( resource );
|
|
|
|
status = FmpChangeResourceNode(resource, NodeId, Add);
|
|
FmpReleaseLocalResourceLock( resource );
|
|
OmDereferenceObject( resource );
|
|
|
|
return(status);
|
|
|
|
} // FmsChangeResourceNode
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsArbitrateResource(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arbitrates a Resource for a remote system.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
ResourceId - The Id of the Resource to bring online.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE resource;
|
|
DWORD status;
|
|
|
|
//
|
|
// Find the specified resource.
|
|
//
|
|
resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
|
|
|
|
if ( resource == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsArbitrateResource: Could not find Resource %1!ws!\n",
|
|
ResourceId);
|
|
return(ERROR_RESOURCE_NOT_FOUND);
|
|
}
|
|
|
|
status = FmpRmArbitrateResource( resource );
|
|
|
|
OmDereferenceObject( resource );
|
|
|
|
return(status);
|
|
|
|
} // FmsArbitrateResource
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsQueryOwnedGroups(
|
|
IN handle_t IDL_handle,
|
|
OUT PGROUP_ENUM *OwnedGroups,
|
|
OUT PRESOURCE_ENUM *OwnedResources
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Server side used to propagate FM state to a joining node.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - Supplies RPC binding handle, not used.
|
|
|
|
OwnedGroups - Returns the list of groups owned by this node and
|
|
their state.
|
|
|
|
OwnedResources - Returns the list of resources contained by groups
|
|
owned by this node and their state.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful
|
|
|
|
Win32 error otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD status = ERROR_SUCCESS;
|
|
DWORD allocated;
|
|
PGROUP_ENUM groupEnum = NULL;
|
|
PFM_GROUP group;
|
|
PRESOURCE_ENUM resourceEnum = NULL;
|
|
PFM_RESOURCE resource;
|
|
DWORD i;
|
|
|
|
allocated = ENUM_GROW_SIZE;
|
|
|
|
groupEnum = MIDL_user_allocate(GROUP_SIZE(allocated));
|
|
if ( groupEnum == NULL ) {
|
|
CL_LOGFAILURE(ERROR_NOT_ENOUGH_MEMORY);
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
groupEnum->EntryCount = 0;
|
|
//
|
|
// Enumerate all groups
|
|
//
|
|
OmEnumObjects( ObjectTypeGroup,
|
|
FmpEnumMyGroups,
|
|
&groupEnum,
|
|
&allocated );
|
|
|
|
//
|
|
// Enumerate all the resources in each group.
|
|
//
|
|
allocated = ENUM_GROW_SIZE;
|
|
resourceEnum = MIDL_user_allocate(RESOURCE_SIZE(allocated));
|
|
if (resourceEnum == NULL) {
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
CL_LOGFAILURE(status);
|
|
goto error_exit;
|
|
}
|
|
resourceEnum->EntryCount = 0;
|
|
|
|
for (i=0; i < groupEnum->EntryCount; i++) {
|
|
//
|
|
// Get the group given its name.
|
|
//
|
|
group = OmReferenceObjectById( ObjectTypeGroup,
|
|
groupEnum->Entry[i].Id );
|
|
if (group == NULL) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Enumerate all the resources in this group.
|
|
//
|
|
status = FmpEnumerateGroupResources(group,
|
|
FmpEnumResources,
|
|
&resourceEnum,
|
|
&allocated);
|
|
if ( status != ERROR_SUCCESS ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsQueryOwnedGroups: Failed group '%1!ws!', status %2!u!.\n",
|
|
OmObjectId(group),
|
|
status);
|
|
}
|
|
OmDereferenceObject(group);
|
|
}
|
|
|
|
*OwnedGroups = groupEnum;
|
|
*OwnedResources = resourceEnum;
|
|
|
|
return(ERROR_SUCCESS);
|
|
|
|
error_exit:
|
|
if (groupEnum != NULL) {
|
|
//
|
|
// Free up group enum
|
|
//
|
|
for (i=0; i < groupEnum->EntryCount; i++) {
|
|
MIDL_user_free(groupEnum->Entry[i].Id);
|
|
}
|
|
MIDL_user_free(groupEnum);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
|
|
error_status_t
|
|
s_FmsFailResource(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Resource Fail Request from a remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
ResourceId - The Id of the Resource to fail.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE resource;
|
|
DWORD status;
|
|
|
|
FmpMustBeOnline( );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsFailResource: To fail resource '%1!ws!'.\n",
|
|
ResourceId);
|
|
|
|
//
|
|
// Find the specified resource.
|
|
//
|
|
resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
|
|
|
|
if ( resource == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsFailResource: Could not find Resource %1!ws!\n",
|
|
ResourceId);
|
|
return(ERROR_RESOURCE_NOT_FOUND);
|
|
}
|
|
|
|
FmpAcquireLocalResourceLock( resource );
|
|
|
|
//
|
|
// Now fail it.
|
|
//
|
|
if ( resource->Group->OwnerNode == NmLocalNode ) {
|
|
status = FmpRmFailResource( resource );
|
|
} else {
|
|
status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
}
|
|
|
|
FmpReleaseLocalResourceLock( resource );
|
|
|
|
return(status);
|
|
|
|
} // FmsFailResource
|
|
|
|
|
|
error_status_t
|
|
s_FmsCreateResource(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR GroupId,
|
|
IN LPWSTR ResourceId,
|
|
IN LPCWSTR ResourceName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Create Resource Request from a remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
GroupId - The Id of the Group to create the resource inside.
|
|
ResourceId - The Id of the Resource to create.
|
|
ResourceName - The name of the Resource to create.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
Notes:
|
|
|
|
The Resource lock is acquired to synchronize access to the resource. This
|
|
satisfies locking the resource on all nodes in the cluster... so long
|
|
as the local node is the owner of the resource.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_GROUP group;
|
|
DWORD status;
|
|
PGUM_CREATE_RESOURCE gumResource;
|
|
DWORD groupIdLen;
|
|
DWORD resourceIdLen;
|
|
DWORD resourceNameLen;
|
|
DWORD bufSize;
|
|
HDMKEY resourceKey;
|
|
HDMKEY paramsKey;
|
|
DWORD disposition;
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsCreateResource: To create resource '%1!ws!'\n",
|
|
ResourceId);
|
|
|
|
//
|
|
// Find the specified group.
|
|
//
|
|
group = OmReferenceObjectById( ObjectTypeGroup,
|
|
GroupId );
|
|
|
|
if ( group == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsCreateResource: Could not find Group %1!ws!\n",
|
|
GroupId);
|
|
return(ERROR_GROUP_NOT_FOUND);
|
|
}
|
|
|
|
FmpAcquireLocalGroupLock( group );
|
|
|
|
//
|
|
// Now delete it on all nodes in the cluster if we are the owner.
|
|
//
|
|
if ( group->OwnerNode == NmLocalNode ) {
|
|
//
|
|
// Allocate a message buffer.
|
|
//
|
|
groupIdLen = (lstrlenW(GroupId)+1) * sizeof(WCHAR);
|
|
resourceIdLen = (lstrlenW(ResourceId)+1) * sizeof(WCHAR);
|
|
resourceNameLen = (lstrlenW(ResourceName)+1) * sizeof(WCHAR);
|
|
bufSize = sizeof(GUM_CREATE_RESOURCE) - sizeof(WCHAR) +
|
|
groupIdLen + resourceIdLen + resourceNameLen;
|
|
gumResource = LocalAlloc(LMEM_FIXED, bufSize);
|
|
if (gumResource == NULL) {
|
|
ClRtlLogPrint(LOG_CRITICAL, "[FM] FmsCreateResource: Unable to allocate memory for resource %1!ws!\n",
|
|
ResourceName);
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
//
|
|
// Fill in message buffer.
|
|
//
|
|
gumResource->Resource = NULL;
|
|
gumResource->GroupIdLen = groupIdLen;
|
|
gumResource->ResourceIdLen = resourceIdLen;
|
|
CopyMemory(gumResource->GroupId, GroupId, groupIdLen);
|
|
CopyMemory((PCHAR)gumResource->GroupId + groupIdLen,
|
|
ResourceId,
|
|
resourceIdLen);
|
|
CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen,
|
|
ResourceName,
|
|
resourceNameLen);
|
|
|
|
//
|
|
// Send message.
|
|
//
|
|
status = GumSendUpdate(GumUpdateFailoverManager,
|
|
FmUpdateCreateResource,
|
|
bufSize,
|
|
gumResource);
|
|
if ( ( status == ERROR_SUCCESS ) &&
|
|
( gumResource->Resource != NULL ) )
|
|
FmpCleanupPossibleNodeList(gumResource->Resource);
|
|
LocalFree(gumResource);
|
|
} else {
|
|
status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
}
|
|
|
|
FmpReleaseLocalGroupLock( group );
|
|
|
|
return(status);
|
|
|
|
} // FmsCreateResource
|
|
|
|
|
|
error_status_t
|
|
s_FmsDeleteResource(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Delete Resource Request from a remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
ResourceId - The Id of the Resource to delete.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
Notes:
|
|
|
|
The Resource lock is acquired to synchronize access to the resource. This
|
|
satisfies locking the resource on all nodes in the cluster... so long
|
|
as the local node is the owner of the resource.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE resource;
|
|
DWORD status;
|
|
DWORD resourceLen;
|
|
|
|
FmpMustBeOnline();
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsDeleteResource: To delete resource '%1!ws!'\n",
|
|
ResourceId);
|
|
|
|
//
|
|
// Find the specified resource.
|
|
//
|
|
resource = OmReferenceObjectById( ObjectTypeResource,
|
|
ResourceId );
|
|
|
|
if ( resource == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsDeleteResource: Could not find Resource %1!ws!\n",
|
|
ResourceId);
|
|
return(ERROR_RESOURCE_NOT_FOUND);
|
|
}
|
|
|
|
FmpAcquireLocalResourceLock( resource );
|
|
|
|
//
|
|
// Now delete it on all nodes in the cluster if we are the owner.
|
|
//
|
|
if ( resource->Group->OwnerNode == NmLocalNode ) {
|
|
//
|
|
// Check if this is the quorum resource.
|
|
//
|
|
if ( resource->QuorumResource ) {
|
|
status = ERROR_QUORUM_RESOURCE;
|
|
goto FnExit;
|
|
}
|
|
|
|
//other core resources cannot be deleted either
|
|
if (resource->ExFlags & CLUS_FLAG_CORE)
|
|
{
|
|
status = ERROR_CORE_RESOURCE;
|
|
goto FnExit;
|
|
}
|
|
|
|
|
|
//
|
|
// Check the state of the resource, before attempting to delete it.
|
|
// It must be offline or failed in order to perform the delete.
|
|
//
|
|
if ((resource->State != ClusterResourceOffline) &&
|
|
(resource->State != ClusterResourceFailed)) {
|
|
status = ERROR_RESOURCE_ONLINE;
|
|
goto FnExit;
|
|
}
|
|
|
|
//
|
|
// Check whether this resource provides for any other resources.
|
|
// If so, it cannot be deleted.
|
|
//
|
|
if (!IsListEmpty(&resource->ProvidesFor)) {
|
|
status = ERROR_DEPENDENT_RESOURCE_EXISTS;
|
|
goto FnExit;
|
|
}
|
|
|
|
if (resource->Group->MovingList)
|
|
{
|
|
status = ERROR_INVALID_STATE;
|
|
goto FnExit;
|
|
}
|
|
|
|
resourceLen = (lstrlenW(ResourceId)+1) * sizeof(WCHAR);
|
|
|
|
FmpBroadcastDeleteControl(resource);
|
|
//
|
|
// Send message.
|
|
//
|
|
status = GumSendUpdateEx(GumUpdateFailoverManager,
|
|
FmUpdateDeleteResource,
|
|
1,
|
|
resourceLen,
|
|
ResourceId);
|
|
} else {
|
|
|
|
status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
|
|
}
|
|
|
|
|
|
FnExit:
|
|
FmpReleaseLocalResourceLock( resource );
|
|
return(status);
|
|
|
|
} // FmsDeleteResource
|
|
|
|
|
|
BOOL
|
|
FmpEnumMyGroups(
|
|
IN OUT PGROUP_ENUM *Enum,
|
|
IN LPDWORD Allocated,
|
|
IN PFM_GROUP Group,
|
|
IN LPCWSTR Id
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Worker callback routine for the enumeration of Groups.
|
|
This routine adds the specified Group to the list that is being
|
|
generated if it is owned by the local system.
|
|
|
|
Arguments:
|
|
|
|
Enum - The Group Enumeration list. Can be an output if a new list is
|
|
allocated.
|
|
Allocated - The current number of allocated entries in Enum.
|
|
Group - The Group object being enumerated.
|
|
Id - The Id of the Group object being enumerated.
|
|
|
|
Returns:
|
|
|
|
TRUE - to indicate that the enumeration should continue.
|
|
|
|
--*/
|
|
|
|
{
|
|
PGROUP_ENUM groupEnum;
|
|
PGROUP_ENUM newEnum;
|
|
DWORD newAllocated;
|
|
DWORD index;
|
|
LPWSTR newId;
|
|
CLUSTER_GROUP_STATE state;
|
|
|
|
//
|
|
// If we don't own the Group, return now.
|
|
//
|
|
if (Group->OwnerNode != NmLocalNode) {
|
|
return(TRUE);
|
|
}
|
|
|
|
groupEnum = *Enum;
|
|
|
|
if ( groupEnum->EntryCount >= *Allocated ) {
|
|
//
|
|
// Time to grow the GROUP_ENUM
|
|
//
|
|
|
|
newAllocated = *Allocated + ENUM_GROW_SIZE;
|
|
newEnum = MIDL_user_allocate(GROUP_SIZE(newAllocated));
|
|
if ( newEnum == NULL ) {
|
|
return(FALSE);
|
|
}
|
|
|
|
CopyMemory(newEnum, groupEnum, GROUP_SIZE(*Allocated));
|
|
*Allocated = newAllocated;
|
|
*Enum = newEnum;
|
|
MIDL_user_free(groupEnum);
|
|
groupEnum = newEnum;
|
|
}
|
|
|
|
//
|
|
// Initialize new entry
|
|
//
|
|
newId = MIDL_user_allocate((lstrlenW(Id)+1) * sizeof(WCHAR));
|
|
if ( newId == NULL ) {
|
|
return(FALSE);
|
|
}
|
|
|
|
lstrcpyW(newId, Id);
|
|
groupEnum->Entry[groupEnum->EntryCount].Id = newId;
|
|
groupEnum->Entry[groupEnum->EntryCount].State = Group->State;
|
|
groupEnum->Entry[groupEnum->EntryCount].StateSequence = Group->StateSequence;
|
|
++groupEnum->EntryCount;
|
|
|
|
return(TRUE);
|
|
|
|
} // FmpEnumMyGroups
|
|
|
|
|
|
BOOL
|
|
FmpEnumResources(
|
|
IN OUT PRESOURCE_ENUM *Enum,
|
|
IN LPDWORD Allocated,
|
|
IN PFM_RESOURCE Resource,
|
|
IN LPCWSTR Id
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Worker callback routine for the enumeration of Group resources.
|
|
This routine adds the specified resource to the list that is being
|
|
generated.
|
|
|
|
Arguments:
|
|
|
|
Enum - The resource enumeration list. Can be an output if a new list is
|
|
allocated.
|
|
Allocated - The current number of allocated entries in Enum.
|
|
Resource - The Resource object being enumerated.
|
|
Id - The Id of the resource object being enumerated.
|
|
|
|
Returns:
|
|
|
|
TRUE - to indicate that the enumeration should continue.
|
|
FALSE - to indicate that the enumeration should not continue.
|
|
|
|
--*/
|
|
|
|
{
|
|
PRESOURCE_ENUM resourceEnum;
|
|
PRESOURCE_ENUM newEnum;
|
|
DWORD newAllocated;
|
|
DWORD index;
|
|
LPWSTR newId;
|
|
|
|
resourceEnum = *Enum;
|
|
|
|
if ( resourceEnum->EntryCount >= *Allocated ) {
|
|
//
|
|
// Time to grow the RESOURCE_ENUM
|
|
//
|
|
newAllocated = *Allocated + ENUM_GROW_SIZE;
|
|
newEnum = MIDL_user_allocate(RESOURCE_SIZE(newAllocated));
|
|
if ( newEnum == NULL ) {
|
|
return(FALSE);
|
|
}
|
|
|
|
CopyMemory(newEnum, resourceEnum, RESOURCE_SIZE(*Allocated));
|
|
*Allocated = newAllocated;
|
|
*Enum = newEnum;
|
|
MIDL_user_free(resourceEnum);
|
|
resourceEnum = newEnum;
|
|
}
|
|
|
|
//
|
|
// Initialize new entry
|
|
//
|
|
newId = MIDL_user_allocate((lstrlenW(Id)+1) * sizeof(WCHAR));
|
|
if ( newId == NULL ) {
|
|
return(FALSE);
|
|
}
|
|
|
|
lstrcpyW(newId, Id);
|
|
resourceEnum->Entry[resourceEnum->EntryCount].Id = newId;
|
|
resourceEnum->Entry[resourceEnum->EntryCount].State = Resource->State;
|
|
resourceEnum->Entry[resourceEnum->EntryCount].StateSequence = Resource->StateSequence;
|
|
++resourceEnum->EntryCount;
|
|
|
|
return(TRUE);
|
|
|
|
} // FmpEnumResources
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsResourceControl(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceId,
|
|
IN DWORD ControlCode,
|
|
IN PUCHAR InBuffer,
|
|
IN DWORD InBufferSize,
|
|
OUT PUCHAR OutBuffer,
|
|
IN DWORD OutBufferSize,
|
|
OUT LPDWORD BytesReturned,
|
|
OUT LPDWORD Required
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine passes a resource control request from a remote system.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - the binding context - not used
|
|
|
|
ResourceId - the Id of the Resource to control
|
|
|
|
ControlCode - the control code for this request
|
|
|
|
InBuffer - the input buffer
|
|
|
|
InBufferSize - the size of the input buffer
|
|
|
|
OutBuffer - the output buffer
|
|
|
|
OutBufferSize - the size of the output buffer
|
|
|
|
ByteReturned - the number of bytes returned in the output buffer
|
|
|
|
Required - the number of bytes required if OutBuffer is not big enough.
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE resource;
|
|
DWORD status;
|
|
DWORD bufSize;
|
|
DWORD dataLength;
|
|
CLUSPROP_BUFFER_HELPER props;
|
|
|
|
//
|
|
// Find the specified resource.
|
|
//
|
|
resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
|
|
|
|
if ( resource == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsResourceControl: Could not find Resource %1!ws!\n",
|
|
ResourceId);
|
|
return(ERROR_RESOURCE_NOT_FOUND);
|
|
}
|
|
|
|
//
|
|
// Since lpInBuffer is declared as [unique] in the IDL file, it can be NULL while dwBufferSize
|
|
// is non-zero and vice-versa. To avoid confusion in the following code, we make them consistent
|
|
// right here.
|
|
//
|
|
if ( InBuffer == NULL )
|
|
{
|
|
InBufferSize = 0;
|
|
}
|
|
else if ( InBufferSize == 0 )
|
|
{
|
|
InBuffer = NULL;
|
|
}
|
|
|
|
CL_ASSERT( resource->Group != NULL );
|
|
|
|
status = FmpRmResourceControl( resource,
|
|
ControlCode,
|
|
InBuffer,
|
|
InBufferSize,
|
|
OutBuffer,
|
|
OutBufferSize,
|
|
BytesReturned,
|
|
Required
|
|
);
|
|
OmDereferenceObject(resource);
|
|
|
|
return(status);
|
|
} // FmsResourceControl
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsResourceTypeControl(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceTypeName,
|
|
IN DWORD ControlCode,
|
|
IN PUCHAR InBuffer,
|
|
IN DWORD InBufferSize,
|
|
OUT PUCHAR OutBuffer,
|
|
IN DWORD OutBufferSize,
|
|
OUT LPDWORD BytesReturned,
|
|
OUT LPDWORD Required
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine passes a resource control request from a remote system.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - the binding context - not used
|
|
|
|
ResourceTypeName - the name of the Resource Type to control
|
|
|
|
ControlCode - the control code for this request
|
|
|
|
InBuffer - the input buffer
|
|
|
|
InBufferSize - the size of the input buffer
|
|
|
|
OutBuffer - the output buffer
|
|
|
|
OutBufferSize - the size of the output buffer
|
|
|
|
ByteReturned - the number of bytes returned in the output buffer
|
|
|
|
Required - the number of bytes required if OutBuffer is not big enough.
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE resource;
|
|
DWORD status;
|
|
|
|
//
|
|
// Since lpInBuffer is declared as [unique] in the IDL file, it can be NULL while dwBufferSize
|
|
// is non-zero and vice-versa. To avoid confusion in the following code, we make them consistent
|
|
// right here.
|
|
//
|
|
if ( InBuffer == NULL )
|
|
{
|
|
InBufferSize = 0;
|
|
}
|
|
else if ( InBufferSize == 0 )
|
|
{
|
|
InBuffer = NULL;
|
|
}
|
|
|
|
status = FmpRmResourceTypeControl( ResourceTypeName,
|
|
ControlCode,
|
|
InBuffer,
|
|
InBufferSize,
|
|
OutBuffer,
|
|
OutBufferSize,
|
|
BytesReturned,
|
|
Required
|
|
);
|
|
|
|
if ((status == ERROR_MOD_NOT_FOUND) || (status == ERROR_PROC_NOT_FOUND))
|
|
{
|
|
FmpRemovePossibleNodeForResType(ResourceTypeName, NmLocalNode);
|
|
}
|
|
#if 0
|
|
if ( ((status == ERROR_SUCCESS) ||
|
|
(status == ERROR_RESOURCE_PROPERTIES_STORED)) &&
|
|
(ControlCode & CLCTL_MODIFY_MASK) ) {
|
|
ClusterEvent( CLUSTER_EVENT_RESTYPE_PROPERTY_CHANGE, XXX );
|
|
}
|
|
#endif
|
|
|
|
return(status);
|
|
|
|
} // FmsResourceTypeControl
|
|
|
|
|
|
error_status_t
|
|
s_FmsGroupControl(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR GroupId,
|
|
IN DWORD ControlCode,
|
|
IN PUCHAR InBuffer,
|
|
IN DWORD InBufferSize,
|
|
OUT PUCHAR OutBuffer,
|
|
IN DWORD OutBufferSize,
|
|
OUT LPDWORD BytesReturned,
|
|
OUT LPDWORD Required
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine processes a group control request from a remote system.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - the binding context - not used
|
|
|
|
GroupId - the Id of the Group to control
|
|
|
|
ControlCode - the control code for this request
|
|
|
|
InBuffer - the input buffer
|
|
|
|
InBufferSize - the size of the input buffer
|
|
|
|
OutBuffer - the output buffer
|
|
|
|
OutBufferSize - the size of the output buffer
|
|
|
|
ByteReturned - the number of bytes returned in the output buffer
|
|
|
|
Required - the number of bytes required if OutBuffer is not big enough.
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
Win32 error code on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_GROUP group;
|
|
DWORD status;
|
|
|
|
//
|
|
// Find the specified group
|
|
//
|
|
group = OmReferenceObjectById( ObjectTypeGroup, GroupId );
|
|
|
|
if ( group == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsGroupControl: Could not find Group %1!ws!\n",
|
|
GroupId);
|
|
return(ERROR_GROUP_NOT_FOUND);
|
|
}
|
|
|
|
//
|
|
// Since lpInBuffer is declared as [unique] in the IDL file, it can be NULL while dwBufferSize
|
|
// is non-zero and vice-versa. To avoid confusion in the following code, we make them consistent
|
|
// right here.
|
|
//
|
|
if ( InBuffer == NULL )
|
|
{
|
|
InBufferSize = 0;
|
|
}
|
|
else if ( InBufferSize == 0 )
|
|
{
|
|
InBuffer = NULL;
|
|
}
|
|
|
|
status = FmpGroupControl(group, ControlCode, InBuffer, InBufferSize,
|
|
OutBuffer, OutBufferSize, BytesReturned, Required);
|
|
|
|
OmDereferenceObject(group);
|
|
return(status);
|
|
|
|
} // FmsGroupControl
|
|
|
|
|
|
error_status_t
|
|
s_FmsPrepareQuorumResChange(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceId,
|
|
IN LPCWSTR lpszQuoLogPath,
|
|
IN DWORD dwMaxQuoLogSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a request to prepare a resource to become the quorum resource.
|
|
A resource must be able to support a quorum log file and registry replication
|
|
files.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
ResourceId - The Id of the resource to be made the quorum resource.
|
|
lpszQuoLogPath - The path where the logs must be created.
|
|
dwMaxQuoLogSize - The maximum size of the quorum log file.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE pResource=NULL;
|
|
DWORD Status;
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsPrepareQuorumResChange: Entry\r\n");
|
|
|
|
// Find the specified resource.
|
|
//
|
|
pResource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
|
|
|
|
if ( pResource == NULL )
|
|
{
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsPrepareQuorumResource: Could not find Resource %1!ws!\n",
|
|
ResourceId);
|
|
Status = ERROR_RESOURCE_NOT_FOUND;
|
|
goto FnExit;
|
|
}
|
|
|
|
CL_ASSERT( pResource->Group != NULL );
|
|
if ( pResource->Group->OwnerNode == NmLocalNode )
|
|
Status = FmpPrepareQuorumResChange(pResource, lpszQuoLogPath, dwMaxQuoLogSize);
|
|
else
|
|
Status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
|
|
FnExit:
|
|
if (pResource) OmDereferenceObject( pResource );
|
|
return(Status);
|
|
|
|
} // FmsPrepareQuorumResChange
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsCompleteQuorumResChange(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR lpszOldQuoResId,
|
|
IN LPCWSTR lpszOldQuoLogPath
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a request to clean up quorum logging and cluster registry files
|
|
on the old quorum resource.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
lpszOldQuoResId - The Id of the resource to be made the quorum resource.
|
|
lpszQuoLogPath - The path where the logs must be created.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE pResource=NULL;
|
|
DWORD Status;
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsCompleteQuorumResChange: Entry\r\n");
|
|
|
|
// Find the specified resource.
|
|
//
|
|
pResource = OmReferenceObjectById( ObjectTypeResource, lpszOldQuoResId );
|
|
|
|
if ( pResource == NULL )
|
|
{
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsCompleteQuorumResource: Could not find Resource %1!ws!\n",
|
|
lpszOldQuoResId);
|
|
Status = ERROR_RESOURCE_NOT_FOUND;
|
|
goto FnExit;
|
|
}
|
|
|
|
CL_ASSERT( pResource->Group != NULL );
|
|
if ( pResource->Group->OwnerNode == NmLocalNode )
|
|
Status = FmpCompleteQuorumResChange(lpszOldQuoResId, lpszOldQuoLogPath);
|
|
else
|
|
Status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
|
|
FnExit:
|
|
if (pResource) OmDereferenceObject( pResource );
|
|
return(Status);
|
|
|
|
} // FmsCompleteQuorumResChange
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsQuoNodeOnlineResource(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceId,
|
|
IN LPCWSTR NodeId,
|
|
OUT LPDWORD State
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a RmResourceOnline request from (THE) remote system and returns
|
|
status for that request.
|
|
|
|
This system must own the quorum resource.
|
|
|
|
This is the first half of the sling shot. We acquire locks
|
|
and then RPC back to the originating node with a request to perform
|
|
the online.
|
|
|
|
This request is only valid for non-quorum resources.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
|
|
ResourceId - The Id of the Resource to bring online.
|
|
|
|
NodeId - The Id of the Node that originated the request.
|
|
|
|
State - Returns the new state of the resource.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
{
|
|
//not used
|
|
return(ERROR_INVALID_FUNCTION);
|
|
}
|
|
// FmsQuoNodeOnlineResource
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsQuoNodeOfflineResource(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceId,
|
|
IN LPCWSTR NodeId,
|
|
OUT LPDWORD State
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Resource Offline Request from (THE) remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
|
|
ResourceId - The Id of the Resource to bring offline.
|
|
|
|
NodeId - The Id of the Node that originated the request.
|
|
|
|
State - Returns the new state of the resource.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
{
|
|
//not used
|
|
return(ERROR_INVALID_FUNCTION);
|
|
}// FmsQuoNodeOfflineResource
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsRmOnlineResource(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceId,
|
|
OUT LPDWORD pdwState
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a RmResourceOnline request from quorum node and returns
|
|
status for that request.
|
|
|
|
This system was the originator of the original online request.
|
|
|
|
This is the second half of the sling shot. It just does the online
|
|
request.
|
|
|
|
This request is only valid for non-quorum resources.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
|
|
ResourceId - The Id of the Resource to bring online.
|
|
|
|
State - Returns the new state of the resource.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
Notes:
|
|
|
|
We can't acquire any locks... but the originating thread has the
|
|
lock held for us.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE resource;
|
|
DWORD status;
|
|
|
|
FmpMustBeOnline( );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsRmOnlineResource: To bring resource '%1!ws!' online\n",
|
|
ResourceId);
|
|
|
|
//
|
|
// Find the specified resource.
|
|
//
|
|
resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
|
|
|
|
if ( resource == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsRmOnlineResource: Could not find Resource %1!ws!\n",
|
|
ResourceId);
|
|
return(ERROR_RESOURCE_NOT_FOUND);
|
|
}
|
|
|
|
//
|
|
// This must not be done on the quorum resource, and the local system
|
|
// must not own the quorum resource. We'll assume that the quorum
|
|
// resource migrated while we were performng this request.
|
|
//
|
|
CL_ASSERT( gpQuoResource != NULL );
|
|
CL_ASSERT( gpQuoResource->Group != NULL );
|
|
CL_ASSERT( gpQuoResource->Group->OwnerNode != NULL );
|
|
|
|
if ( resource->QuorumResource ||
|
|
(gpQuoResource->Group->OwnerNode == NmLocalNode) ) {
|
|
OmDereferenceObject( resource );
|
|
return(ERROR_HOST_NODE_NOT_RESOURCE_OWNER);
|
|
}
|
|
|
|
//
|
|
// The local node must own the resource.
|
|
//
|
|
CL_ASSERT( resource->Group != NULL );
|
|
CL_ASSERT( resource->Group->OwnerNode != NULL );
|
|
if ( resource->Group->OwnerNode != NmLocalNode ) {
|
|
OmDereferenceObject( resource );
|
|
return(ERROR_RESOURCE_NOT_AVAILABLE);
|
|
}
|
|
|
|
//
|
|
// Just call the function that does the work.
|
|
//
|
|
OmNotifyCb( resource, NOTIFY_RESOURCE_PREONLINE );
|
|
|
|
status = RmOnlineResource( resource->Id, pdwState );
|
|
//call the synchronous notifications on the resource
|
|
FmpCallResourceNotifyCb(resource, *pdwState);
|
|
|
|
OmDereferenceObject( resource );
|
|
|
|
return(status);
|
|
|
|
} // FmsRmOnlineResource
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsRmOfflineResource(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceId,
|
|
OUT LPDWORD pdwState
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Resource Offline Request from (THE) remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
|
|
ResourceId - The Id of the Resource to bring offline.
|
|
|
|
State - Returns the new state of the resource.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
Notes:
|
|
|
|
We can't acquire any locks... but the originating thread has the
|
|
lock held for us.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE resource;
|
|
DWORD status;
|
|
|
|
FmpMustBeOnline( );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsRmOfflineResource: To take resource '%1!ws!' offline\n",
|
|
ResourceId);
|
|
|
|
//
|
|
// Find the specified resource.
|
|
//
|
|
resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
|
|
|
|
if ( resource == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsRmOfflineResource: Could not find Resource %1!ws!\n",
|
|
ResourceId);
|
|
return(ERROR_RESOURCE_NOT_FOUND);
|
|
}
|
|
|
|
//
|
|
// This must not be done on the quorum resource, and the local system
|
|
// must not own the quorum resource. We'll assume that the quorum
|
|
// resource migrated while we were performng this request.
|
|
//
|
|
CL_ASSERT( gpQuoResource != NULL );
|
|
CL_ASSERT( gpQuoResource->Group != NULL );
|
|
CL_ASSERT( gpQuoResource->Group->OwnerNode != NULL );
|
|
|
|
if ( resource->QuorumResource ||
|
|
(gpQuoResource->Group->OwnerNode == NmLocalNode) ) {
|
|
OmDereferenceObject( resource );
|
|
return(ERROR_HOST_NODE_NOT_RESOURCE_OWNER);
|
|
}
|
|
|
|
//
|
|
// The local node must own the resource.
|
|
//
|
|
CL_ASSERT( resource->Group != NULL );
|
|
CL_ASSERT( resource->Group->OwnerNode != NULL );
|
|
if ( resource->Group->OwnerNode != NmLocalNode ) {
|
|
OmDereferenceObject( resource );
|
|
return(ERROR_RESOURCE_NOT_AVAILABLE);
|
|
}
|
|
|
|
//
|
|
// Just call the function that does the work.
|
|
//
|
|
OmNotifyCb( resource, NOTIFY_RESOURCE_PREOFFLINE );
|
|
|
|
status = RmOfflineResource( resource->Id, pdwState );
|
|
|
|
//call the post offline obj synchronous notifications
|
|
FmpCallResourceNotifyCb(resource, *pdwState);
|
|
|
|
OmDereferenceObject( resource );
|
|
|
|
return(status);
|
|
|
|
} // FmsRmOfflineResource
|
|
|
|
error_status_t
|
|
s_FmsBackupClusterDatabase(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR ResourceId,
|
|
IN LPCWSTR lpszPathName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a request to backup the quorum log file and the checkpoint
|
|
file
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
ResourceId - The Id of the quorum resource
|
|
lpszPathName - The directory path name where the files have to be
|
|
backed up. This path must be visible to the node
|
|
on which the quorum resource is online.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE pResource = NULL;
|
|
DWORD Status;
|
|
|
|
FmpMustBeOnline( );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsBackupClusterDatabase: Entry...\r\n");
|
|
|
|
//
|
|
// Chittur Subbaraman (chitturs) - 10/12/1998
|
|
//
|
|
// Find the specified quorum resource
|
|
//
|
|
pResource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
|
|
|
|
if ( pResource == NULL )
|
|
{
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsBackupClusterDatabase: Could not find Resource %1!ws!\n",
|
|
ResourceId);
|
|
Status = ERROR_RESOURCE_NOT_FOUND;
|
|
goto FnExit;
|
|
}
|
|
|
|
FmpAcquireLocalResourceLock( pResource );
|
|
|
|
CL_ASSERT( pResource->Group != NULL );
|
|
|
|
//
|
|
// Make sure the local node owns the quorum resource
|
|
//
|
|
if ( pResource->Group->OwnerNode == NmLocalNode )
|
|
{
|
|
Status = FmpBackupClusterDatabase( pResource, lpszPathName );
|
|
}
|
|
else
|
|
{
|
|
Status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsBackupClusterDatabase: This node is not the quorum resource owner...\n"
|
|
);
|
|
}
|
|
|
|
FmpReleaseLocalResourceLock( pResource );
|
|
|
|
FnExit:
|
|
if ( pResource ) OmDereferenceObject( pResource );
|
|
return( Status );
|
|
} // FmsBackupClusterDatabase
|
|
|
|
error_status_t
|
|
s_FmsChangeResourceGroup(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR pszResourceId,
|
|
IN LPCWSTR pszGroupId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Resource change group request from a remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
pszResourceId - The Id of the Resource to change a resource
|
|
pszGroupId - The Id of the Group to change to.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE pResource = NULL;
|
|
PFM_GROUP pNewGroup = NULL;
|
|
DWORD dwStatus;
|
|
PFM_GROUP pOldGroup;
|
|
|
|
FmpMustBeOnline( );
|
|
|
|
//
|
|
// Find the specified resource.
|
|
//
|
|
pResource = OmReferenceObjectById( ObjectTypeResource, pszResourceId );
|
|
|
|
if ( pResource == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsChangeResourceNode: Could not find Resource %1!ws!\n",
|
|
pszResourceId);
|
|
dwStatus = ERROR_RESOURCE_NOT_FOUND;
|
|
goto FnExit;
|
|
}
|
|
|
|
//
|
|
// Find the specified group.
|
|
//
|
|
pNewGroup = OmReferenceObjectById( ObjectTypeGroup, pszGroupId );
|
|
|
|
if ( pNewGroup == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsChangeResourceGroupe: Could not find NewGroup %1!ws!\n",
|
|
pszGroupId);
|
|
dwStatus = ERROR_GROUP_NOT_FOUND;
|
|
goto FnExit;
|
|
}
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmChangeResourceGroup : Resource <%1!ws!> NewGroup %2!ws!\n",
|
|
OmObjectId( pResource ),
|
|
OmObjectId( pNewGroup ));
|
|
|
|
//
|
|
// Synchronize both the old and the new groups.
|
|
// Lock the lowest by lowest Group Id first - to prevent deadlocks!
|
|
// Note - the order of release is unimportant.
|
|
//
|
|
// strictly, the comparison below cannot be equal!
|
|
//
|
|
if ( lstrcmpiW( OmObjectId( pResource->Group ), OmObjectId( pNewGroup ) ) <= 0 ) {
|
|
FmpAcquireLocalGroupLock( pResource->Group );
|
|
FmpAcquireLocalGroupLock( pNewGroup );
|
|
} else {
|
|
FmpAcquireLocalGroupLock( pNewGroup );
|
|
FmpAcquireLocalGroupLock( pResource->Group );
|
|
}
|
|
|
|
//remember the old group for freeing locks
|
|
pOldGroup = pResource->Group;
|
|
|
|
//boy if we are not the owner any more
|
|
//shunt the request to the new owner
|
|
if ( pResource->Group->OwnerNode != NmLocalNode )
|
|
{
|
|
// Note: FmcChangeResourceNode must release the resource lock.
|
|
dwStatus = FmcChangeResourceGroup( pResource, pNewGroup );
|
|
goto FnExit;
|
|
}
|
|
else
|
|
{
|
|
dwStatus = FmpChangeResourceGroup( pResource, pNewGroup );
|
|
}
|
|
|
|
FmpReleaseLocalGroupLock( pNewGroup );
|
|
FmpReleaseLocalGroupLock( pOldGroup );
|
|
|
|
FnExit:
|
|
if ( pResource ) OmDereferenceObject( pResource );
|
|
if ( pNewGroup ) OmDereferenceObject( pNewGroup );
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsChangeResourceGroup : returned <%1!u!>\r\n",
|
|
dwStatus);
|
|
return( dwStatus );
|
|
} //s_FmsChangeResourceGroup
|
|
|
|
|
|
|
|
error_status_t
|
|
s_FmsDeleteGroupRequest(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR pszGroupId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a delete group request from a remote system and returns
|
|
the status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
pszGroupId - The Id of the group to be deleted.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_GROUP pGroup = NULL;
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
|
|
FmpMustBeOnline( );
|
|
|
|
//
|
|
// Find the specified group.
|
|
//
|
|
pGroup = OmReferenceObjectById( ObjectTypeGroup, pszGroupId );
|
|
|
|
if ( pGroup == NULL )
|
|
{
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsDeleteGroupRequest: Could not find group %1!ws!\n",
|
|
pszGroupId);
|
|
dwStatus = ERROR_GROUP_NOT_FOUND;
|
|
goto FnExit;
|
|
}
|
|
|
|
FmpAcquireLocalGroupLock( pGroup );
|
|
|
|
if ( pGroup->OwnerNode == NmLocalNode )
|
|
{
|
|
dwStatus = FmpDeleteGroup( pGroup );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// FmcDeleteGroup releases the group lock
|
|
//
|
|
dwStatus = FmcDeleteGroupRequest( pGroup );
|
|
goto FnExit;
|
|
}
|
|
|
|
FmpReleaseLocalGroupLock( pGroup );
|
|
|
|
FnExit:
|
|
if ( pGroup ) OmDereferenceObject( pGroup );
|
|
return( dwStatus );
|
|
} //s_FmsChangeResourceGroup
|
|
|
|
|
|
error_status_t
|
|
s_FmsAddResourceDependency(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR pszResourceId,
|
|
IN LPCWSTR pszDependsOnId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives an add resource dependency request from a remote system
|
|
and returns the status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
|
|
pszResourceId - The Id of the resource to add a dependent resource.
|
|
|
|
pszDependentResourceId - The Id of the dependent resource.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE pResource = NULL;
|
|
PFM_RESOURCE pDependentResource = NULL;
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
DWORD dwResourceLen;
|
|
DWORD dwDependsOnLen;
|
|
|
|
//
|
|
// Chittur Subbaraman (chitturs) - 5/16/99
|
|
//
|
|
// Handle add resource dependency RPC calls from non-owner nodes
|
|
//
|
|
FmpMustBeOnline( );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsAddResourceDependency: Resource <%1!ws!>, Dependent Resource <%2!ws!>\n",
|
|
pszResourceId,
|
|
pszDependsOnId);
|
|
|
|
//
|
|
// Find the specified resources.
|
|
//
|
|
pResource = OmReferenceObjectById( ObjectTypeResource, pszResourceId );
|
|
|
|
if ( pResource == NULL )
|
|
{
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsAddResourceDependency: Could not find resource <%1!ws!>\n",
|
|
pszResourceId);
|
|
dwStatus = ERROR_RESOURCE_NOT_FOUND;
|
|
goto FnExit;
|
|
}
|
|
|
|
pDependentResource = OmReferenceObjectById( ObjectTypeResource,
|
|
pszDependsOnId );
|
|
|
|
if ( pDependentResource == NULL )
|
|
{
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsAddResourceDependency: Could not find dependent resource <%1!ws!>\n",
|
|
pszDependsOnId);
|
|
dwStatus = ERROR_RESOURCE_NOT_FOUND;
|
|
goto FnExit;
|
|
}
|
|
//
|
|
// Acquire the resource lock
|
|
//
|
|
FmpAcquireLocalResourceLock( pResource );
|
|
|
|
if ( pResource->Group->OwnerNode != NmLocalNode )
|
|
{
|
|
dwStatus = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
goto FnUnlock;
|
|
}
|
|
|
|
dwStatus = FmpValAddResourceDependency( pResource, pDependentResource );
|
|
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
goto FnUnlock;
|
|
}
|
|
|
|
dwResourceLen = ( lstrlenW( pszResourceId ) + 1 ) * sizeof( WCHAR );
|
|
|
|
dwDependsOnLen = ( lstrlenW( pszDependsOnId ) + 1 ) * sizeof( WCHAR );
|
|
|
|
|
|
dwStatus = GumSendUpdateEx( GumUpdateFailoverManager,
|
|
FmUpdateAddDependency,
|
|
2,
|
|
dwResourceLen,
|
|
pszResourceId,
|
|
dwDependsOnLen,
|
|
pszDependsOnId );
|
|
|
|
if ( dwStatus == ERROR_SUCCESS )
|
|
{
|
|
FmpBroadcastDependencyChange( pResource,
|
|
pszDependsOnId,
|
|
FALSE );
|
|
}
|
|
|
|
FnUnlock:
|
|
FmpReleaseLocalResourceLock( pResource );
|
|
|
|
|
|
FnExit:
|
|
if ( pResource ) OmDereferenceObject( pResource );
|
|
|
|
if ( pDependentResource ) OmDereferenceObject( pDependentResource );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsAddResourceDependency Exit: Status = %1!u!\n",
|
|
dwStatus);
|
|
|
|
return( dwStatus );
|
|
} // s_FmsAddResourceDependency
|
|
|
|
error_status_t
|
|
s_FmsRemoveResourceDependency(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR pszResourceId,
|
|
IN LPCWSTR pszDependsOnId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a remove resource dependency request from a remote system
|
|
and returns the status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
|
|
pszResourceId - The Id of the resource to remove a dependent resource from.
|
|
|
|
pszDependentResourceId - The Id of the dependent resource.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_RESOURCE pResource = NULL;
|
|
PFM_RESOURCE pDependentResource = NULL;
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
DWORD dwResourceLen;
|
|
DWORD dwDependsOnLen;
|
|
|
|
//
|
|
// Chittur Subbaraman (chitturs) - 5/16/99
|
|
//
|
|
// Handle remove resource dependency RPC calls from non-owner nodes
|
|
//
|
|
FmpMustBeOnline( );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsRemoveResourceDependency: Resource <%1!ws!>, Dependent Resource <%2!ws!>\n",
|
|
pszResourceId,
|
|
pszDependsOnId);
|
|
|
|
//
|
|
// Find the specified resources.
|
|
//
|
|
pResource = OmReferenceObjectById( ObjectTypeResource, pszResourceId );
|
|
|
|
if ( pResource == NULL )
|
|
{
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsRemoveResourceDependency: Could not find resource <%1!ws!>\n",
|
|
pszResourceId);
|
|
dwStatus = ERROR_RESOURCE_NOT_FOUND;
|
|
goto FnExit;
|
|
}
|
|
|
|
pDependentResource = OmReferenceObjectById( ObjectTypeResource,
|
|
pszDependsOnId );
|
|
|
|
if ( pDependentResource == NULL )
|
|
{
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsRemoveResourceDependency: Could not find dependent resource <%1!ws!>\n",
|
|
pszDependsOnId);
|
|
dwStatus = ERROR_RESOURCE_NOT_FOUND;
|
|
goto FnExit;
|
|
}
|
|
//
|
|
// Acquire the resource lock
|
|
//
|
|
FmpAcquireLocalResourceLock( pResource );
|
|
|
|
dwStatus = FmpValRemoveResourceDependency( pResource, pDependentResource );
|
|
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] s_FmsRemoveResourceDependency: FmpValRemoveResourceDependency returns %1!u!\n",
|
|
dwStatus);
|
|
goto FnUnlock;
|
|
}
|
|
|
|
if ( pResource->Group->OwnerNode != NmLocalNode )
|
|
{
|
|
dwStatus = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
goto FnUnlock;
|
|
}
|
|
|
|
pszResourceId = OmObjectId( pResource );
|
|
dwResourceLen = ( lstrlenW( pszResourceId ) + 1 ) * sizeof( WCHAR );
|
|
|
|
pszDependsOnId = OmObjectId( pDependentResource );
|
|
dwDependsOnLen = ( lstrlenW( pszDependsOnId ) + 1 ) * sizeof( WCHAR );
|
|
|
|
|
|
dwStatus = GumSendUpdateEx( GumUpdateFailoverManager,
|
|
FmUpdateRemoveDependency,
|
|
2,
|
|
dwResourceLen,
|
|
pszResourceId,
|
|
dwDependsOnLen,
|
|
pszDependsOnId );
|
|
|
|
if ( dwStatus == ERROR_SUCCESS )
|
|
{
|
|
FmpBroadcastDependencyChange( pResource,
|
|
pszDependsOnId,
|
|
TRUE );
|
|
}
|
|
|
|
FnUnlock:
|
|
FmpReleaseLocalResourceLock( pResource );
|
|
|
|
FnExit:
|
|
if ( pResource ) OmDereferenceObject( pResource );
|
|
|
|
if ( pDependentResource ) OmDereferenceObject( pDependentResource );
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsRemoveResourceDependency Exit: Status = %1!u!\n",
|
|
dwStatus);
|
|
|
|
return( dwStatus );
|
|
} // s_FmsRemoveResourceDependency
|
|
|
|
error_status_t
|
|
s_FmsCreateResource2(
|
|
IN handle_t IDL_handle,
|
|
IN LPCWSTR GroupId,
|
|
IN LPWSTR ResourceId,
|
|
IN LPCWSTR ResourceName,
|
|
IN LPCWSTR ResourceType,
|
|
IN DWORD dwFlags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a Create Resource Request from a remote system and returns
|
|
status for that request.
|
|
|
|
Arguments:
|
|
|
|
IDL_handle - The binding context - not used.
|
|
GroupId - The Id of the Group to create the resource inside.
|
|
ResourceId - The Id of the Resource to create.
|
|
ResourceName - The name of the Resource to create.
|
|
ResourceType - The name of the Resource Type.
|
|
dwFlags - Flags for the resource.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
|
|
A Win32 error code on error.
|
|
|
|
Notes:
|
|
|
|
The Resource lock is acquired to synchronize access to the resource. This
|
|
satisfies locking the resource on all nodes in the cluster... so long
|
|
as the local node is the owner of the resource.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFM_GROUP group;
|
|
DWORD status;
|
|
PGUM_CREATE_RESOURCE gumResource;
|
|
DWORD groupIdLen;
|
|
DWORD resourceIdLen;
|
|
DWORD resourceNameLen;
|
|
DWORD resourceTypeLen;
|
|
DWORD bufSize;
|
|
HDMKEY resourceKey;
|
|
HDMKEY paramsKey;
|
|
DWORD disposition;
|
|
|
|
FmpMustBeOnline();
|
|
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsCreateResource2: To create resource '%1!ws!'\n",
|
|
ResourceId);
|
|
|
|
//
|
|
// Find the specified group.
|
|
//
|
|
group = OmReferenceObjectById( ObjectTypeGroup,
|
|
GroupId );
|
|
|
|
if ( group == NULL ) {
|
|
ClRtlLogPrint(LOG_NOISE,
|
|
"[FM] FmsCreateResource2: Could not find Group %1!ws!\n",
|
|
GroupId);
|
|
return(ERROR_GROUP_NOT_FOUND);
|
|
}
|
|
|
|
FmpAcquireLocalGroupLock( group );
|
|
|
|
//
|
|
// Now delete it on all nodes in the cluster if we are the owner.
|
|
//
|
|
if ( group->OwnerNode == NmLocalNode ) {
|
|
//
|
|
// Allocate a message buffer.
|
|
//
|
|
groupIdLen = (lstrlenW(GroupId)+1) * sizeof(WCHAR);
|
|
resourceIdLen = (lstrlenW(ResourceId)+1) * sizeof(WCHAR);
|
|
resourceNameLen = (lstrlenW(ResourceName)+1) * sizeof(WCHAR);
|
|
resourceTypeLen = (lstrlenW(ResourceType)+1) * sizeof(WCHAR);
|
|
bufSize = sizeof(GUM_CREATE_RESOURCE) - sizeof(WCHAR) +
|
|
groupIdLen + resourceIdLen + resourceNameLen + resourceTypeLen + 2 * sizeof( DWORD );
|
|
gumResource = LocalAlloc(LMEM_FIXED, bufSize);
|
|
if (gumResource == NULL) {
|
|
ClRtlLogPrint(LOG_CRITICAL, "[FM] FmsCreateResource2: Unable to allocate memory for resource %1!ws!\n",
|
|
ResourceName);
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
//
|
|
// Fill in message buffer.
|
|
//
|
|
gumResource->Resource = NULL;
|
|
gumResource->GroupIdLen = groupIdLen;
|
|
gumResource->ResourceIdLen = resourceIdLen;
|
|
CopyMemory(gumResource->GroupId, GroupId, groupIdLen);
|
|
CopyMemory((PCHAR)gumResource->GroupId + groupIdLen,
|
|
ResourceId,
|
|
resourceIdLen);
|
|
CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen,
|
|
ResourceName,
|
|
resourceNameLen);
|
|
|
|
CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen + resourceNameLen,
|
|
&resourceTypeLen,
|
|
sizeof( DWORD ) );
|
|
|
|
CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen + resourceNameLen + sizeof( DWORD ),
|
|
ResourceType,
|
|
resourceTypeLen );
|
|
|
|
CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen + resourceNameLen + sizeof( DWORD ) + resourceTypeLen,
|
|
&dwFlags,
|
|
sizeof( DWORD ) );
|
|
//
|
|
// Send message.
|
|
//
|
|
status = GumSendUpdate(GumUpdateFailoverManager,
|
|
FmUpdateCreateResource,
|
|
bufSize,
|
|
gumResource);
|
|
if ( ( status == ERROR_SUCCESS ) &&
|
|
( gumResource->Resource != NULL ) )
|
|
{
|
|
//
|
|
// If the GUM call was successful, ensure that the resource DLL initialization stuff is
|
|
// also done so that APIs following the CreateClusterResource API can make assumptions
|
|
// that the resource is fully created. Note that the GUM call above will post a work item
|
|
// for the FM worker thread to initialize a resource but there is no guarantee when the
|
|
// FM worker thread will act on the work item. The following call will make sure we
|
|
// won't return from this API until the initialization is fully done thus not giving any
|
|
// chance for APIs such as ChangeClusterResourceGroup that follow this API to screw things
|
|
// up. For backward compatibility reasons (consider a create call originating from a
|
|
// W2K node), we still keep the work item posting in GUM and it won't do any harm since
|
|
// the FmpInitializeResource call is idempotent.
|
|
//
|
|
FmpClusterWideInitializeResource ( gumResource->Resource );
|
|
FmpCleanupPossibleNodeList(gumResource->Resource);
|
|
}
|
|
|
|
if( ( gumResource->Resource == NULL ) && FmpShutdown ) {
|
|
status = ERROR_CLUSTER_NODE_SHUTTING_DOWN;
|
|
}
|
|
LocalFree(gumResource);
|
|
} else {
|
|
status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
|
|
}
|
|
|
|
FmpReleaseLocalGroupLock( group );
|
|
|
|
return(status);
|
|
|
|
} // FmsCreateResource2
|