|
|
#include "WLBS_Provider.h"
#include "WLBS_Node.h"
#include "ClusterWrapper.h"
#include "ControlWrapper.h"
#include "utils.h"
#include "wlbsutil.h"
////////////////////////////////////////////////////////////////////////////////
//
// CWLBS_Node::CWLBS_Node
//
// Purpose: Constructor
//
////////////////////////////////////////////////////////////////////////////////
CWLBS_Node::CWLBS_Node(CWbemServices* a_pNameSpace, IWbemObjectSink* a_pResponseHandler) : CWlbs_Root( a_pNameSpace, a_pResponseHandler ) {
}
////////////////////////////////////////////////////////////////////////////////
//
// CWLBS_Node::Create
//
// Purpose: This instantiates this class and is invoked from an array of
// function pointers.
//
////////////////////////////////////////////////////////////////////////////////
CWlbs_Root* CWLBS_Node::Create ( CWbemServices* a_pNameSpace, IWbemObjectSink* a_pResponseHandler ) {
g_pWlbsControl->CheckMembership();
CWlbs_Root* pRoot = new CWLBS_Node( a_pNameSpace, a_pResponseHandler );
if( !pRoot ) throw _com_error( WBEM_E_OUT_OF_MEMORY );
return pRoot; }
////////////////////////////////////////////////////////////////////////////////
//
// CWLBS_Node::GetInstance
//
// Purpose: Queries WLBS for desired node instance and sends results back
// to WinMgMt.
//
////////////////////////////////////////////////////////////////////////////////
HRESULT CWLBS_Node::GetInstance ( const ParsedObjectPath* a_pParsedPath, long /* a_lFlags */, IWbemContext* /* a_pIContex */ ) { IWbemClassObject* pWlbsInstance = NULL; HRESULT hRes = 0;
try {
//g_pWlbsControl->CheckConfiguration();
//get the node
FindInstance( &pWlbsInstance, a_pParsedPath );
//send the results back to WinMgMt
m_pResponseHandler->Indicate( 1, &pWlbsInstance );
if( pWlbsInstance ) { pWlbsInstance->Release(); pWlbsInstance = NULL; }
m_pResponseHandler->SetStatus( 0, WBEM_S_NO_ERROR, NULL, NULL );
hRes = WBEM_S_NO_ERROR; }
catch(CErrorWlbsControl Err) {
IWbemClassObject* pWbemExtStat = NULL;
CreateExtendedStatus( m_pNameSpace, &pWbemExtStat, Err.Error(), (PWCHAR)(Err.Description()) );
m_pResponseHandler->SetStatus(0, WBEM_E_FAILED, NULL, pWbemExtStat);
if( pWbemExtStat ) pWbemExtStat->Release();
if( pWlbsInstance ) pWlbsInstance->Release();
//do not return WBEM_E_FAILED, this causes a race condition
hRes = WBEM_S_NO_ERROR; }
catch(_com_error HResErr ) {
m_pResponseHandler->SetStatus(0, HResErr.Error(), NULL, NULL);
if( pWlbsInstance ) pWlbsInstance->Release();
hRes = HResErr.Error(); }
catch(...) {
if( pWlbsInstance ) { pWlbsInstance->Release(); pWlbsInstance = NULL; }
throw;
}
return hRes; }
////////////////////////////////////////////////////////////////////////////////
//
// CWLBS_Node::EnumInstances
//
// Purpose: Executes a WlbsQuery and sends data back to WinMgMt.
//
////////////////////////////////////////////////////////////////////////////////
HRESULT CWLBS_Node::EnumInstances ( BSTR /* a_bstrClass */, long /* a_lFlags */, IWbemContext* /* a_pIContex */ ) { IWbemClassObject** ppWlbsInstance = NULL; WLBS_RESPONSE* pResponse = NULL; HRESULT hRes = 0;
BSTR strClassName = NULL; long nNumNodes = 0; //g_pWlbsControl->CheckConfiguration();
try {
strClassName = SysAllocString( MOF_NODE::szName );
if( !strClassName ) throw _com_error( WBEM_E_OUT_OF_MEMORY );
//declare an IWbemClassObject smart pointer
IWbemClassObjectPtr pWlbsNodeClass;
//get the MOF class object
hRes = m_pNameSpace->GetObject( strClassName, 0, NULL, &pWlbsNodeClass, NULL );
if( FAILED( hRes ) ) { throw _com_error( hRes ); }
DWORD dwNumClusters = 0; CWlbsClusterWrapper** ppCluster = NULL;
g_pWlbsControl->EnumClusters(ppCluster, &dwNumClusters); if (dwNumClusters == 0) { throw _com_error( WBEM_E_NOT_FOUND ); }
for (DWORD iCluster=0; iCluster<dwNumClusters; iCluster++) {
//call the API query function to find the nodes
try { FindAllInstances(ppCluster[iCluster], &pResponse, nNumNodes ); } catch (CErrorWlbsControl Err) { //
// Skip this cluster
//
TRACE_ERROR1("CWLBS_Node::EnumInstances skiped cluster %x", ppCluster[iCluster]->GetClusterIP()); continue; }
//spawn an instance of the Node MOF class for each node found
ppWlbsInstance = new IWbemClassObject *[nNumNodes];
if( !ppWlbsInstance ) throw _com_error( WBEM_E_OUT_OF_MEMORY );
//initialize array
ZeroMemory( ppWlbsInstance, nNumNodes * sizeof(IWbemClassObject *) );
for(int i = 0; i < nNumNodes; i ++ ) { hRes = pWlbsNodeClass->SpawnInstance( 0, &ppWlbsInstance[i] );
if( FAILED( hRes ) ) throw _com_error( hRes );
FillWbemInstance(ppCluster[iCluster], ppWlbsInstance[i], pResponse + i ); }
//send the results back to WinMgMt
hRes = m_pResponseHandler->Indicate( nNumNodes, ppWlbsInstance );
if( FAILED( hRes ) ) { throw _com_error( hRes ); }
if( ppWlbsInstance ) { for( i = 0; i < nNumNodes; i++ ) { if( ppWlbsInstance[i] ) { ppWlbsInstance[i]->Release(); } } delete [] ppWlbsInstance; }
if( pResponse ) delete [] pResponse; }
if( strClassName ) SysFreeString(strClassName);
m_pResponseHandler->SetStatus( 0, WBEM_S_NO_ERROR, NULL, NULL );
hRes = WBEM_S_NO_ERROR; }
catch(CErrorWlbsControl Err) {
IWbemClassObject* pWbemExtStat = NULL;
CreateExtendedStatus( m_pNameSpace, &pWbemExtStat, Err.Error(), (PWCHAR)(Err.Description()) );
m_pResponseHandler->SetStatus(0, WBEM_E_FAILED, NULL, pWbemExtStat);
if( pWbemExtStat ) pWbemExtStat->Release();
if( strClassName ) SysFreeString( strClassName );
if( ppWlbsInstance ) { for(int i = 0; i < nNumNodes; i++ ) { if( ppWlbsInstance[i] ) { ppWlbsInstance[i]->Release(); } } delete [] ppWlbsInstance; }
if( pResponse ) delete [] pResponse;
//do not return WBEM_E_FAILED, this causes a race condition
hRes = WBEM_S_NO_ERROR; }
catch(_com_error HResErr ) {
m_pResponseHandler->SetStatus(0, HResErr.Error(), NULL, NULL);
if( strClassName ) SysFreeString( strClassName );
if( ppWlbsInstance ) { for(int i = 0; i < nNumNodes; i++ ) { if( ppWlbsInstance[i] ) { ppWlbsInstance[i]->Release(); } } delete [] ppWlbsInstance; }
if( pResponse ) delete [] pResponse;
hRes = HResErr.Error(); }
catch(...) {
if( strClassName ) SysFreeString( strClassName );
if( ppWlbsInstance ) { for(int i = 0; i < nNumNodes; i++ ) { if( ppWlbsInstance[i] ) { ppWlbsInstance[i]->Release(); } } delete [] ppWlbsInstance; }
if( pResponse ) delete [] pResponse;
throw;
}
return hRes; }
////////////////////////////////////////////////////////////////////////////////
//
// CWLBS_Node::ExecMethod
//
// Purpose: This executes the methods associated with the MOF
// Node class.
//
////////////////////////////////////////////////////////////////////////////////
HRESULT CWLBS_Node::ExecMethod ( const ParsedObjectPath* a_pParsedPath, const BSTR& a_strMethodName, long /* a_lFlags */, IWbemContext* /* a_pIContex */, IWbemClassObject* a_pIInParams ) {
DWORD dwNumHosts = 1; DWORD dwReturnValue;
HRESULT hRes = 0;
_variant_t vMofResponse; _variant_t vReturnValue; _variant_t vInputPortNumber; CNodeConfiguration NodeConfig;
BSTR strPortNumber = NULL;
IWbemClassObject* pOutputInstance = NULL;
try {
strPortNumber = SysAllocString( MOF_PARAM::PORT_NUMBER );
if( !strPortNumber ) throw _com_error( WBEM_E_OUT_OF_MEMORY );
//get the host ID address
DWORD dwHostID = 0; DWORD dwClusterIpOrIndex = 0; dwHostID = ExtractHostID( wstring( (*a_pParsedPath->m_paKeys)->m_vValue.bstrVal ) ); if ((DWORD)-1 == dwHostID) throw _com_error( WBEM_E_NOT_FOUND );
dwClusterIpOrIndex = ExtractClusterIP( wstring( (*a_pParsedPath->m_paKeys)->m_vValue.bstrVal ) ); if ((DWORD)-1 == dwClusterIpOrIndex) throw _com_error( WBEM_E_NOT_FOUND ); CWlbsClusterWrapper* pCluster = g_pWlbsControl->GetClusterFromIpOrIndex(dwClusterIpOrIndex);
if (pCluster == NULL) throw _com_error( WBEM_E_NOT_FOUND ); //always let the provider peform control operations on the local host
if( dwHostID == pCluster->GetHostID() ) dwHostID = WLBS_LOCAL_HOST; //get the output object instance
GetMethodOutputInstance( MOF_NODE::szName, a_strMethodName, &pOutputInstance );
//determine and execute the MOF method
if( _wcsicmp(a_strMethodName, MOF_NODE::pMethods[MOF_NODE::DISABLE] ) == 0) { if( !a_pIInParams ) throw _com_error( WBEM_E_INVALID_PARAMETER );
// The "Disable" method does NOT take vip as a parameter, so, if there is any port rule
// that is specific to a vip (other than the "all vip"), we fail this method.
// The "EffectiveVersion" registry value is checked for a value of CVY_VERSION_FULL to
// see of there is any port rule that is specific to a vip
pCluster->GetNodeConfig(NodeConfig); if(NodeConfig.dwEffectiveVersion == CVY_VERSION_FULL) throw _com_error( WBEM_E_INVALID_OPERATION );
//get the port number
hRes = a_pIInParams->Get ( strPortNumber, 0, &vInputPortNumber, NULL, NULL );
if( FAILED( hRes ) ) { throw _com_error( hRes ); }
//make sure the port number is not NULL
if( vInputPortNumber.vt != VT_I4) throw _com_error( WBEM_E_INVALID_PARAMETER );
//call Disable method
dwReturnValue = g_pWlbsControl->Disable ( pCluster->GetClusterIpOrIndex(g_pWlbsControl), dwHostID, NULL, dwNumHosts, IpAddressFromAbcdWsz(CVY_DEF_ALL_VIP), // "All Vip"
(long)vInputPortNumber );
} else if(_wcsicmp(a_strMethodName, MOF_NODE::pMethods[MOF_NODE::ENABLE] ) == 0) {
if( !a_pIInParams ) throw _com_error( WBEM_E_INVALID_PARAMETER );
// The "Enable" method does NOT take vip as a parameter, so, if there is any port rule
// that is specific to a vip (other than the "all vip"), we fail this method.
// The "EffectiveVersion" registry value is checked for a value of CVY_VERSION_FULL to
// see of there is any port rule that is specific to a vip
pCluster->GetNodeConfig(NodeConfig); if(NodeConfig.dwEffectiveVersion == CVY_VERSION_FULL) throw _com_error( WBEM_E_INVALID_OPERATION );
//get the port number
hRes = a_pIInParams->Get ( strPortNumber, 0, &vInputPortNumber, NULL, NULL );
if( FAILED( hRes ) ) { throw _com_error( hRes ); }
if( vInputPortNumber.vt != VT_I4) throw _com_error(WBEM_E_INVALID_PARAMETER);
//call Enable method
dwReturnValue = g_pWlbsControl->Enable ( pCluster->GetClusterIpOrIndex(g_pWlbsControl), dwHostID, NULL, dwNumHosts, IpAddressFromAbcdWsz(CVY_DEF_ALL_VIP), // "All Vip"
(long)vInputPortNumber );
} else if(_wcsicmp(a_strMethodName, MOF_NODE::pMethods[MOF_NODE::DRAIN] ) == 0) {
if( !a_pIInParams ) throw _com_error( WBEM_E_INVALID_PARAMETER );
// The "Drain" method does NOT take vip as a parameter, so, if there is any port rule
// that is specific to a vip (other than the "all vip"), we fail this method.
// The "EffectiveVersion" registry value is checked for a value of CVY_VERSION_FULL to
// see of there is any port rule that is specific to a vip
pCluster->GetNodeConfig(NodeConfig); if(NodeConfig.dwEffectiveVersion == CVY_VERSION_FULL) throw _com_error( WBEM_E_INVALID_OPERATION );
//get the port number
hRes = a_pIInParams->Get ( strPortNumber, 0, &vInputPortNumber, NULL, NULL );
if( FAILED( hRes ) ) { throw _com_error( hRes ); }
if( vInputPortNumber.vt != VT_I4) throw _com_error(WBEM_E_INVALID_PARAMETER);
//call Drain method
dwReturnValue = g_pWlbsControl->Drain ( pCluster->GetClusterIpOrIndex(g_pWlbsControl), dwHostID, NULL, dwNumHosts, IpAddressFromAbcdWsz(CVY_DEF_ALL_VIP), // "All Vip"
(long)vInputPortNumber );
} else if(_wcsicmp(a_strMethodName, MOF_NODE::pMethods[MOF_NODE::DRAINSTOP]) == 0) {
//call DrainStop method
dwReturnValue = g_pWlbsControl->DrainStop( pCluster->GetClusterIpOrIndex(g_pWlbsControl), dwHostID, NULL, dwNumHosts);
} else if(_wcsicmp(a_strMethodName, MOF_NODE::pMethods[MOF_NODE::RESUME] ) == 0) {
//call Resume method
dwReturnValue = g_pWlbsControl->Resume( pCluster->GetClusterIpOrIndex(g_pWlbsControl), dwHostID, NULL, dwNumHosts);
} else if(_wcsicmp(a_strMethodName, MOF_NODE::pMethods[MOF_NODE::START] ) == 0) {
//call Start method
dwReturnValue = g_pWlbsControl->Start( pCluster->GetClusterIpOrIndex(g_pWlbsControl), dwHostID, NULL, dwNumHosts);
} else if(_wcsicmp(a_strMethodName, MOF_NODE::pMethods[MOF_NODE::STOP] ) == 0) {
//call Stop method
dwReturnValue = g_pWlbsControl->Stop( pCluster->GetClusterIpOrIndex(g_pWlbsControl), dwHostID, NULL, dwNumHosts);
} else if(_wcsicmp(a_strMethodName, MOF_NODE::pMethods[MOF_NODE::SUSPEND] ) == 0) {
//call Suspend method
dwReturnValue = g_pWlbsControl->Suspend( pCluster->GetClusterIpOrIndex(g_pWlbsControl), dwHostID, NULL, dwNumHosts);
} else {
throw _com_error(WBEM_E_METHOD_NOT_IMPLEMENTED); }
//set the return value
vReturnValue = (long)dwReturnValue; hRes = pOutputInstance->Put( _bstr_t(L"ReturnValue"), 0, &vReturnValue, 0 );
if( FAILED( hRes ) ) { throw _com_error( hRes ); } //send the results back to WinMgMt
hRes = m_pResponseHandler->Indicate(1, &pOutputInstance);
if( FAILED( hRes ) ) { throw _com_error( hRes ); }
if( strPortNumber ) { SysFreeString(strPortNumber); strPortNumber = NULL; }
m_pResponseHandler->SetStatus( 0, WBEM_S_NO_ERROR, NULL, NULL );
hRes = WBEM_S_NO_ERROR; }
catch(CErrorWlbsControl Err) {
IWbemClassObject* pWbemExtStat = NULL;
CreateExtendedStatus( m_pNameSpace, &pWbemExtStat, Err.Error(), (PWCHAR)(Err.Description()) );
m_pResponseHandler->SetStatus(0, WBEM_E_FAILED, NULL, pWbemExtStat);
if( strPortNumber ) { SysFreeString(strPortNumber); strPortNumber = NULL; }
if( pOutputInstance ) { pOutputInstance->Release(); pOutputInstance = NULL; }
if( pWbemExtStat ) pWbemExtStat->Release();
//do not return WBEM_E_FAILED, this causes a race condition
hRes = WBEM_S_NO_ERROR; }
catch(_com_error HResErr ) {
m_pResponseHandler->SetStatus(0, HResErr.Error(), NULL, NULL);
if( strPortNumber ) { SysFreeString(strPortNumber); strPortNumber = NULL; }
if( pOutputInstance ) { pOutputInstance->Release(); pOutputInstance = NULL; }
hRes = HResErr.Error(); }
catch(...) {
if( strPortNumber ) { SysFreeString(strPortNumber); strPortNumber = NULL; }
if( pOutputInstance ) { pOutputInstance->Release(); pOutputInstance = NULL; }
throw;
}
return hRes; }
////////////////////////////////////////////////////////////////////////////////
//
// CWLBS_Node::FindInstance
//
// Purpose: This routine determines if a host is within the local cluster. If
// it is, then the host's data is obtained and returned via the
// IWbemClassObject interface.
//
////////////////////////////////////////////////////////////////////////////////
void CWLBS_Node::FindInstance
( IWbemClassObject** a_ppWbemInstance, const ParsedObjectPath* a_pParsedPath )
{ try { //get the key property
//throws _com_error
//get the name key property and convert to ANSI
//throws _com_error
wstring szRequestedHostName = ( *a_pParsedPath->m_paKeys)->m_vValue.bstrVal;
DWORD dwClustIpOrIndex = ExtractClusterIP( szRequestedHostName );
CWlbsClusterWrapper* pCluster = g_pWlbsControl->GetClusterFromIpOrIndex(dwClustIpOrIndex);
if( pCluster == NULL ) throw _com_error( WBEM_E_NOT_FOUND );
WLBS_RESPONSE Response;
DWORD dwHostID = ExtractHostID( szRequestedHostName ); if ((DWORD)-1 == dwHostID) throw _com_error( WBEM_E_NOT_FOUND );
//always let the provider peform control operations on the local host
if( dwHostID == pCluster->GetHostID() ) { dwHostID = WLBS_LOCAL_HOST; }
DWORD dwNumHosts = 1; //call the api query function
g_pWlbsControl->Query( pCluster, dwHostID , &Response , &dwNumHosts, NULL );
if( dwNumHosts == 0 ) throw _com_error( WBEM_E_NOT_FOUND );
//if requested, fill a MOF instance structure
if(a_ppWbemInstance) {
//get the Wbem class instance
SpawnInstance( MOF_NODE::szName, a_ppWbemInstance );
//Convert status to string description
FillWbemInstance(pCluster, *a_ppWbemInstance, &Response );
} } catch(...) {
if( *a_ppWbemInstance ) {
delete *a_ppWbemInstance; *a_ppWbemInstance = NULL;
}
throw;
} }
////////////////////////////////////////////////////////////////////////////////
//
// CWLBS_Node::FindAllInstances
//
// Purpose: This executes a WLBS query and returns Response structures upon
// success. It always performs a local query to get the local host
// so that disabling remote control will not prevent it from
// enumerating. The dedicated IP address is added to the structure
// within the CWlbsControlWrapper::Query call.
//
////////////////////////////////////////////////////////////////////////////////
void CWLBS_Node::FindAllInstances ( CWlbsClusterWrapper* pCluster, WLBS_RESPONSE** a_ppResponse, long& a_nNumNodes ) { WLBS_RESPONSE Response[WLBS_MAX_HOSTS]; WLBS_RESPONSE LocalResponse;
ASSERT(pCluster); ZeroMemory(Response, WLBS_MAX_HOSTS * sizeof(WLBS_RESPONSE)); DWORD dwNumHosts = WLBS_MAX_HOSTS;
a_nNumNodes = 0; //this will contain the number of nodes returned
try {
//get the local host
DWORD dwLocalNode = 1; g_pWlbsControl->Query( pCluster, WLBS_LOCAL_HOST, &LocalResponse, &dwLocalNode, NULL);
try {
//we only want remote hosts
if( pCluster->GetClusterIP() != 0 ) { g_pWlbsControl->Query( pCluster, WLBS_ALL_HOSTS, Response, &dwNumHosts, NULL ); } else { dwNumHosts = 0; } } catch (CErrorWlbsControl Err) { dwNumHosts = 0; if (Err.Error() != WLBS_TIMEOUT) { throw; } }
//this wastes memory if the local node
//has remote control enabled
a_nNumNodes = dwNumHosts + 1;
if( a_ppResponse ) { *a_ppResponse = new WLBS_RESPONSE[a_nNumNodes];
if( !*a_ppResponse ) throw _com_error( WBEM_E_OUT_OF_MEMORY );
//copy the local host
(*a_ppResponse)[0] = LocalResponse;
int j = 1; for(DWORD i = 1; i <= dwNumHosts; i++ ) { //do not copy the local host again should it have remote control enabled
if( Response[i-1].id == LocalResponse.id ) { //we received the local node twice, so we reduce the count
//by one
a_nNumNodes--; continue; } (*a_ppResponse)[j] = Response[i-1]; j++; }
} } catch (...) {
if ( *a_ppResponse ) { delete [] *a_ppResponse; *a_ppResponse = NULL; }
throw; } }
////////////////////////////////////////////////////////////////////////////////
//
// CWLBS_Node::FillWbemInstance
//
// Purpose: This function copies all of the data from a node configuration
// structure to a WBEM instance.
//
////////////////////////////////////////////////////////////////////////////////
void CWLBS_Node::FillWbemInstance ( CWlbsClusterWrapper* pCluster, IWbemClassObject* a_pWbemInstance, WLBS_RESPONSE* a_pResponse ) { namespace NODE = MOF_NODE;
ASSERT( a_pWbemInstance ); ASSERT( a_pResponse );
wstring wstrHostName;
ConstructHostName( wstrHostName, pCluster->GetClusterIpOrIndex(g_pWlbsControl), a_pResponse->id );
//HOST NAME
HRESULT hRes = a_pWbemInstance->Put ( _bstr_t( NODE::pProperties[NODE::NAME] ) , 0 , &_variant_t(wstrHostName.c_str()), NULL );
if( FAILED( hRes ) ) throw _com_error( hRes );
//HOST ID
hRes = a_pWbemInstance->Put ( _bstr_t( NODE::pProperties[NODE::HOSTID] ) , 0 , &_variant_t((long)(a_pResponse->id)), NULL );
if( FAILED( hRes ) ) throw _com_error( hRes );
//CREATCLASS
hRes = a_pWbemInstance->Put ( _bstr_t( NODE::pProperties[NODE::CREATCLASS] ), 0 , &_variant_t(NODE::szName), NULL );
if( FAILED( hRes ) ) throw _com_error( hRes );
//IP ADDRESS
wstring szIPAddress; AddressToString( a_pResponse->address, szIPAddress ); hRes = a_pWbemInstance->Put ( _bstr_t( NODE::pProperties[NODE::IPADDRESS] ), 0 , &_variant_t(szIPAddress.c_str()), NULL );
if( FAILED( hRes ) ) throw _com_error( hRes );
//STATUS
hRes = a_pWbemInstance->Put ( _bstr_t( NODE::pProperties[NODE::STATUS] ) , 0 , &_variant_t((long)a_pResponse->status), NULL );
if( FAILED( hRes ) ) throw _com_error( hRes ); }
|