version 1.5.2.1, 2005/08/12 22:52:44
|
version 1.6, 2005/01/26 23:09:09
|
|
|
public: | public: |
ProviderAgentContainer( | ProviderAgentContainer( |
const String & moduleName, | const String & moduleName, |
|
const String & userName, |
PEGASUS_INDICATION_CALLBACK indicationCallback); | PEGASUS_INDICATION_CALLBACK indicationCallback); |
| |
~ProviderAgentContainer(); | ~ProviderAgentContainer(); |
| |
Boolean isInitialized(); | Boolean isInitialized(); |
| |
|
String getModuleName() const; |
|
|
CIMResponseMessage* processMessage(CIMRequestMessage* request); | CIMResponseMessage* processMessage(CIMRequestMessage* request); |
void unloadIdleProviders(); | void unloadIdleProviders(); |
| |
|
|
String _moduleName; | String _moduleName; |
| |
/** | /** |
|
The user context in which this Provider Agent operates. |
|
*/ |
|
String _userName; |
|
|
|
/** |
Callback function to which all generated indications are sent for | Callback function to which all generated indications are sent for |
processing. | processing. |
*/ | */ |
|
|
the last provider module instance sent. | the last provider module instance sent. |
*/ | */ |
CIMInstance _providerModuleCache; | CIMInstance _providerModuleCache; |
|
|
|
/** |
|
The number of Provider Agent processes that are currently initialized |
|
(active). |
|
*/ |
|
static Uint32 _numProviderProcesses; |
|
|
|
/** |
|
The _numProviderProcessesMutex must be locked whenever reading or |
|
updating the _numProviderProcesses count. |
|
*/ |
|
static Mutex _numProviderProcessesMutex; |
|
|
|
/** |
|
The maximum number of Provider Agent processes that may be initialized |
|
(active) at one time. |
|
*/ |
|
static Uint32 _maxProviderProcesses; |
}; | }; |
| |
|
Uint32 ProviderAgentContainer::_numProviderProcesses = 0; |
|
Mutex ProviderAgentContainer::_numProviderProcessesMutex; |
|
Uint32 ProviderAgentContainer::_maxProviderProcesses = PEG_NOT_FOUND; |
|
|
ProviderAgentContainer::ProviderAgentContainer( | ProviderAgentContainer::ProviderAgentContainer( |
const String & moduleName, | const String & moduleName, |
|
const String & userName, |
PEGASUS_INDICATION_CALLBACK indicationCallback) | PEGASUS_INDICATION_CALLBACK indicationCallback) |
: _moduleName(moduleName), | : _moduleName(moduleName), |
|
_userName(userName), |
_indicationCallback(indicationCallback), | _indicationCallback(indicationCallback), |
_isInitialized(false) | _isInitialized(false) |
{ | { |
|
|
pipeToAgent->exportReadHandle(readHandle); | pipeToAgent->exportReadHandle(readHandle); |
pipeFromAgent->exportWriteHandle(writeHandle); | pipeFromAgent->exportWriteHandle(writeHandle); |
| |
|
// Set the user context of the Provider Agent process |
|
if (_userName != System::getEffectiveUserName()) |
|
{ |
|
if (!System::changeUserContext(_userName.getCString())) |
|
{ |
|
Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2, |
|
"System::changeUserContext() failed. userName = %s.", |
|
_userName.getCString()); |
|
Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, |
|
Logger::WARNING, |
|
"ProviderManager.OOPProviderManagerRouter." |
|
"USER_CONTEXT_CHANGE_FAILED", |
|
"Unable to change user context to \"$0\".", _userName); |
|
_exit(1); |
|
} |
|
} |
|
|
execl(agentCommandPathCString, agentCommandPathCString, | execl(agentCommandPathCString, agentCommandPathCString, |
readHandle, writeHandle, | readHandle, writeHandle, |
(const char*)_moduleName.getCString(), (char*)0); | (const char*)_moduleName.getCString(), (char*)0); |
|
|
return; | return; |
} | } |
| |
|
if (_maxProviderProcesses == PEG_NOT_FOUND) |
|
{ |
|
String maxProviderProcesses = ConfigManager::getInstance()->getCurrentValue("maxProviderProcesses"); |
|
CString maxProviderProcessesString = maxProviderProcesses.getCString(); |
|
char* end = 0; |
|
_maxProviderProcesses = strtol(maxProviderProcessesString, &end, 10); |
|
} |
|
|
|
{ |
|
AutoMutex lock(_numProviderProcessesMutex); |
|
if ((_maxProviderProcesses != 0) && |
|
(_numProviderProcesses >= _maxProviderProcesses)) |
|
{ |
|
throw PEGASUS_CIM_EXCEPTION( |
|
CIM_ERR_FAILED, |
|
MessageLoaderParms( |
|
"ProviderManager.OOPProviderManagerRouter." |
|
"MAX_PROVIDER_PROCESSES_REACHED", |
|
"The maximum number of cimprovagt processes has been " |
|
"reached.")); |
|
} |
|
else |
|
{ |
|
_numProviderProcesses++; |
|
} |
|
} |
|
|
try | try |
{ | { |
_startAgentProcess(); | _startAgentProcess(); |
|
|
_isInitialized = true; | _isInitialized = true; |
| |
// Start a thread to read and process responses from the Provider Agent | // Start a thread to read and process responses from the Provider Agent |
ThreadStatus rtn = PEGASUS_THREAD_OK; |
while (!MessageQueueService::get_thread_pool()->allocate_and_awaken( |
while ((rtn = MessageQueueService::get_thread_pool()-> |
this, _responseProcessor)) |
allocate_and_awaken(this, _responseProcessor)) != |
|
PEGASUS_THREAD_OK) |
|
{ |
|
if (rtn == PEGASUS_THREAD_INSUFFICIENT_RESOURCES) |
|
{ | { |
pegasus_yield(); | pegasus_yield(); |
} | } |
else |
|
{ |
|
Logger::put( |
|
Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE, |
|
"Not enough threads to process responses from the " |
|
"provider agent."); |
|
|
|
Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2, |
|
"Could not allocate thread to process responses from the " |
|
"provider agent."); |
|
|
|
throw Exception(MessageLoaderParms( |
|
"ProviderManager.OOPProviderManagerRouter." |
|
"CIMPROVAGT_THREAD_ALLOCATION_FAILED", |
|
"Failed to allocate thread for cimprovagt \"$0\".", |
|
_moduleName)); |
|
} |
|
} |
|
} | } |
catch (...) | catch (...) |
{ | { |
_isInitialized = false; | _isInitialized = false; |
_pipeToAgent.reset(); | _pipeToAgent.reset(); |
_pipeFromAgent.reset(); | _pipeFromAgent.reset(); |
|
|
|
{ |
|
AutoMutex lock(_numProviderProcessesMutex); |
|
_numProviderProcesses--; |
|
} |
|
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
throw; | throw; |
} | } |
|
|
| |
_providerModuleCache = CIMInstance(); | _providerModuleCache = CIMInstance(); |
| |
|
{ |
|
AutoMutex lock(_numProviderProcessesMutex); |
|
_numProviderProcesses--; |
|
} |
|
|
_isInitialized = false; | _isInitialized = false; |
| |
// | // |
|
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
} | } |
| |
|
String ProviderAgentContainer::getModuleName() const |
|
{ |
|
return _moduleName; |
|
} |
|
|
CIMResponseMessage* ProviderAgentContainer::processMessage( | CIMResponseMessage* ProviderAgentContainer::processMessage( |
CIMRequestMessage* request) | CIMRequestMessage* request) |
{ | { |
|
|
response.reset(request->buildResponse()); | response.reset(request->buildResponse()); |
} | } |
} | } |
else |
else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE) |
{ | { |
|
// Fan out the request to all Provider Agent processes for this module |
|
|
// Retrieve the provider module name | // Retrieve the provider module name |
String moduleName; | String moduleName; |
CIMValue nameValue = providerModule.getProperty( | CIMValue nameValue = providerModule.getProperty( |
providerModule.findProperty("Name")).getValue(); | providerModule.findProperty("Name")).getValue(); |
nameValue.get(moduleName); | nameValue.get(moduleName); |
| |
// Look up the Provider Agent for this module |
// Look up the Provider Agents for this module |
ProviderAgentContainer * pa = _lookupProviderAgent(moduleName); |
Array<ProviderAgentContainer*> paArray = |
PEGASUS_ASSERT(pa != 0); |
_lookupProviderAgents(moduleName); |
|
|
// Determine whether the Provider Agent has been initialized |
|
Boolean paInitialized = pa->isInitialized(); |
|
| |
if ((request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE) && |
for (Uint32 i=0; i<paArray.size(); i++) |
!paInitialized) |
|
{ | { |
// | // |
// Do not start up an agent process just to disable the module | // Do not start up an agent process just to disable the module |
// | // |
|
if (paArray[i]->isInitialized()) |
|
{ |
|
// |
|
// Forward the request to the provider agent |
|
// |
|
response.reset(paArray[i]->processMessage(request)); |
|
|
|
// Note: Do not uninitialize the ProviderAgentContainer here |
|
// when a disable module operation is successful. Just let the |
|
// selecting thread notice when the agent connection is closed. |
|
|
|
// Determine the success of the disable module operation |
|
CIMDisableModuleResponseMessage* dmResponse = |
|
dynamic_cast<CIMDisableModuleResponseMessage*>( |
|
response.get()); |
|
PEGASUS_ASSERT(dmResponse != 0); |
|
|
|
Boolean isStopped = false; |
|
for (Uint32 i=0; i < dmResponse->operationalStatus.size(); i++) |
|
{ |
|
if (dmResponse->operationalStatus[i] == |
|
CIM_MSE_OPSTATUS_VALUE_STOPPED) |
|
{ |
|
isStopped = true; |
|
break; |
|
} |
|
} |
|
|
|
// If the operation is unsuccessful, stop and return the error |
|
if ((dmResponse->cimException.getCode() != CIM_ERR_SUCCESS) || |
|
!isStopped) |
|
{ |
|
break; |
|
} |
|
} |
|
} |
|
|
|
// Use a default response if no Provider Agents were called |
|
if (!response.get()) |
|
{ |
response.reset(request->buildResponse()); | response.reset(request->buildResponse()); |
| |
CIMDisableModuleResponseMessage* dmResponse = | CIMDisableModuleResponseMessage* dmResponse = |
|
|
operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED); | operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED); |
dmResponse->operationalStatus = operationalStatus; | dmResponse->operationalStatus = operationalStatus; |
} | } |
else if ((request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE) && |
} |
!paInitialized) |
else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE) |
|
{ |
|
// Fan out the request to all Provider Agent processes for this module |
|
|
|
// Retrieve the provider module name |
|
String moduleName; |
|
CIMValue nameValue = providerModule.getProperty( |
|
providerModule.findProperty("Name")).getValue(); |
|
nameValue.get(moduleName); |
|
|
|
// Look up the Provider Agents for this module |
|
Array<ProviderAgentContainer*> paArray = |
|
_lookupProviderAgents(moduleName); |
|
|
|
for (Uint32 i=0; i<paArray.size(); i++) |
{ | { |
// | // |
// Do not start up an agent process just to enable the module | // Do not start up an agent process just to enable the module |
// | // |
|
if (paArray[i]->isInitialized()) |
|
{ |
|
// |
|
// Forward the request to the provider agent |
|
// |
|
response.reset(paArray[i]->processMessage(request)); |
|
|
|
// Determine the success of the enable module operation |
|
CIMEnableModuleResponseMessage* emResponse = |
|
dynamic_cast<CIMEnableModuleResponseMessage*>( |
|
response.get()); |
|
PEGASUS_ASSERT(emResponse != 0); |
|
|
|
Boolean isOk = false; |
|
for (Uint32 i=0; i < emResponse->operationalStatus.size(); i++) |
|
{ |
|
if (emResponse->operationalStatus[i] == |
|
CIM_MSE_OPSTATUS_VALUE_OK) |
|
{ |
|
isOk = true; |
|
break; |
|
} |
|
} |
|
|
|
// If the operation is unsuccessful, stop and return the error |
|
if ((emResponse->cimException.getCode() != CIM_ERR_SUCCESS) || |
|
!isOk) |
|
{ |
|
break; |
|
} |
|
} |
|
} |
|
|
|
// Use a default response if no Provider Agents were called |
|
if (!response.get()) |
|
{ |
response.reset(request->buildResponse()); | response.reset(request->buildResponse()); |
| |
CIMEnableModuleResponseMessage* emResponse = | CIMEnableModuleResponseMessage* emResponse = |
|
|
operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK); | operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK); |
emResponse->operationalStatus = operationalStatus; | emResponse->operationalStatus = operationalStatus; |
} | } |
|
} |
else | else |
{ | { |
|
// Retrieve the provider module name |
|
String moduleName; |
|
CIMValue nameValue = providerModule.getProperty( |
|
providerModule.findProperty("Name")).getValue(); |
|
nameValue.get(moduleName); |
|
|
|
// Retrieve the provider user context configuration |
|
Uint16 userContext = 0; |
|
Uint32 pos = providerModule.findProperty( |
|
PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT); |
|
if (pos != PEG_NOT_FOUND) |
|
{ |
|
providerModule.getProperty(pos).getValue().get(userContext); |
|
} |
|
|
|
if (userContext == 0) |
|
{ |
|
userContext = PG_PROVMODULE_USERCTXT_PRIVILEGED; |
|
} |
|
|
|
String userName; |
|
|
|
if (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR) |
|
{ |
|
try |
|
{ |
|
// User Name is in the OperationContext |
|
IdentityContainer ic = (IdentityContainer) |
|
request->operationContext.get(IdentityContainer::NAME); |
|
userName = ic.getUserName(); |
|
} |
|
catch (Exception& e) |
|
{ |
|
// If no IdentityContainer is present, default to the CIM |
|
// Server's user context |
|
} |
|
|
|
// If authentication is disabled, use the CIM Server's user context |
|
if (!userName.size()) |
|
{ |
|
userName = System::getEffectiveUserName(); |
|
} |
|
} |
|
else if (userContext == PG_PROVMODULE_USERCTXT_DESIGNATED) |
|
{ |
|
// Retrieve the provider module name |
|
providerModule.getProperty(providerModule.findProperty( |
|
PEGASUS_PROPERTYNAME_MODULE_DESIGNATEDUSER)).getValue(). |
|
get(userName); |
|
} |
|
else if (userContext == PG_PROVMODULE_USERCTXT_CIMSERVER) |
|
{ |
|
userName = System::getEffectiveUserName(); |
|
} |
|
else // Privileged User |
|
{ |
|
PEGASUS_ASSERT(userContext == PG_PROVMODULE_USERCTXT_PRIVILEGED); |
|
userName = System::getPrivilegedUserName(); |
|
} |
|
|
|
PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4, |
|
"Module name = " + moduleName); |
|
Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL4, |
|
"User context = %hd.", userContext); |
|
PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4, |
|
"User name = " + userName); |
|
|
|
// Look up the Provider Agent for this module and user |
|
ProviderAgentContainer* pa = _lookupProviderAgent(moduleName, userName); |
|
PEGASUS_ASSERT(pa != 0); |
|
|
// | // |
// Forward the request to the provider agent | // Forward the request to the provider agent |
// | // |
response.reset(pa->processMessage(request)); | response.reset(pa->processMessage(request)); |
|
|
// Note: Do not uninitialize the ProviderAgentContainer here when |
|
// a disable module operation is successful.) Just let the |
|
// selecting thread notice when the agent connection is closed. |
|
} |
|
} | } |
| |
response->syncAttributes(request); | response->syncAttributes(request); |
|
|
} | } |
| |
ProviderAgentContainer* OOPProviderManagerRouter::_lookupProviderAgent( | ProviderAgentContainer* OOPProviderManagerRouter::_lookupProviderAgent( |
const String& moduleName) |
const String& moduleName, |
|
const String& userName) |
{ | { |
ProviderAgentContainer* pa = 0; | ProviderAgentContainer* pa = 0; |
|
String key = moduleName + ":" + userName; |
| |
AutoMutex lock(_providerAgentTableMutex); | AutoMutex lock(_providerAgentTableMutex); |
if (!_providerAgentTable.lookup(moduleName, pa)) |
if (!_providerAgentTable.lookup(key, pa)) |
{ | { |
pa = new ProviderAgentContainer(moduleName, _indicationCallback); |
pa = new ProviderAgentContainer( |
_providerAgentTable.insert(moduleName, pa); |
moduleName, userName, _indicationCallback); |
|
_providerAgentTable.insert(key, pa); |
} | } |
return pa; | return pa; |
} | } |
| |
|
Array<ProviderAgentContainer*> OOPProviderManagerRouter::_lookupProviderAgents( |
|
const String& moduleName) |
|
{ |
|
Array<ProviderAgentContainer*> paArray; |
|
|
|
AutoMutex lock(_providerAgentTableMutex); |
|
for (ProviderAgentTable::Iterator i = _providerAgentTable.start(); i; i++) |
|
{ |
|
if (i.value()->getModuleName() == moduleName) |
|
{ |
|
paArray.append(i.value()); |
|
} |
|
} |
|
return paArray; |
|
} |
|
|
CIMResponseMessage* OOPProviderManagerRouter::_forwardRequestToAllAgents( | CIMResponseMessage* OOPProviderManagerRouter::_forwardRequestToAllAgents( |
CIMRequestMessage* request) | CIMRequestMessage* request) |
{ | { |