Oracle Clusterware manages applications registered as resources with Oracle Clusterware and must have access to application-specific primitives that have the ability to start, stop, and monitor a specific resource. Oracle Clusterware runs all resource-specific commands through an entity called an agent.
An agent is a program that contains the agent framework and user code to manage resources. The agent framework is a C library that enables you to plug in your application-specific code to manage customized applications. You program all of the actual application management functions in C or C++, such as starting, stopping, and checking the health of an application, into the agent. These functions are referred to as entry points. The agent framework is responsible for invoking these entry point functions on behalf of Oracle Clusterware. Agent developers can use these entry points to plug in the required functionality for a specific resource regarding how to start, stop, and monitor a resource. Agents are capable of managing multiple resources.
This appendix includes the following topics:
The Oracle Clusterware agent framework uses Oracle-defined portable data types to represent strings and numbers. By using these data types, you can build and execute agent programs on multiple platforms. Table G-1 lists and describes the Oracle data types used in the agent framework.
Table G-1 Oracle Data Types Used in the Agent Framework
Oracle Data Type | Description |
---|---|
ub4 |
Unsigned 32-bit integer |
sb4 |
Signed 32-bit integer |
oratext* |
C style null-terminated strings, explicit cast to char * required |
The agent framework APIs return a status value of type clsagfwret
, as follows:
CLSAGFW_SUCCESS
: Function executed successfullyCLSAGFW_FAIL
: There was error in the parameters or in execution of the functionString values returned by an API are only accessible in the scope of the current command entry point. Agents can copy the returned string value to its own buffers to retain the value.
The agent framework is initialized by the clsagfw_init()
function call. There is no context that you need to maintain. Action entry point functions are passed a pointer to the agent framework context (type clsagfw_aectx
). This context is specific to the entry point being called and cannot be used beyond the scope of the entry point. Other agent framework APIs take this context pointer as a parameter. This is an opaque data structure that the agent framework maintains but does not explicitly initialize or destroy.
The agent implements the entry point functions for the resource management commands and registers these functions with the agent framework. The agent framework calls an entry point function to execute a command or action on a resource. The entry point functions need to conform to the following prototype and convention:
typedef ub4 (*clsagfw_action_entry) (const clsagfw_aectx *aectx)
The entry point function is called with a pointer to a context area that the agent framework maintains. This function should return a value indicating the status of execution of the entry point. For the CHECK entry point, the function returns the current state of the resource.
If you develop the agent using C++, then you declare the entry point function prototypes using the extern ’C'
keyword.
The agent framework currently defines seven entry point types corresponding to resource management commands and operations performed on a resource. Agents must register entry points for START, STOP, CHECK, and CLEAN commands. Other command entry points are optional. The agent registers entry points by calling the clsagfw_set_entrypoint()
API for each resource type and command. Table G-2 lists and describes entry point types and their equivalent type codes.
Name | Description | Type Code |
---|---|---|
START |
Start a resource and bring it online |
CLSAGFW_ACTION_START |
STOP |
Stop a resource and take it offline |
CLSAGFW_ACTION_STOP |
CLEAN |
Clean up after a failed command on the resource |
CLSAGFW_ACTION_CLEAN |
CHECK |
Check the state of the resource |
CLSAGFW_ACTION_CHECK |
ABORT |
End an executing command that has timed out |
CLSAGFW_ACTION_ABORT |
DELETE |
Resource is about to be deleted |
CLSAGFW_ACTION_RES_DELETED |
MODIFY |
Resource is modified |
CLSAGFW_RESATTR_MODIFIED |
ACTION |
Invoke custom action on the resource |
CLSAGFW_RES_ACTION |
See Also:
"Oracle Clusterware Resources and Agents" for more information about entry pointsAll entry point functions, except for the CHECK entry point, return one of the following values to indicate the status of execution of the entry point:
CLSAGFW_AE_SUCCESS: Entry point execution completed successfully
CLSAGFW_AE_FAIL: Entry point execution failed
The agent framework calls the CHECK entry point function to monitor the state of the resource. This function returns one of the following values that represents the current state of the resource:
See Also:
"Agents" for more information about evaluating and returning the state of a resourceThe Oracle Clusterware agent framework is multithreaded by design. The agent code can also start new threads to execute application-specific functionality, such as monitoring external event sources. The agent framework executes only one entry point of a resource at a time, with the only exception being the ABORT entry point which is invoked to end a currently active action on a resource. C and C++ developers must ensure that all agent code is multithread safe. Access to global variables and other resources must be serialized using locking mechanisms, such mutexes. Other external C or C++ libraries included by the agent should also be multithread safe.
Table G-3 lists the deprecated agent framework APIs and the corresponding replacement APIs for Oracle Clusterware.
This section lists and describes the following functions:
The clsagfw_add_type()
function registers a resource type that the agent manages.
The clsagfw_check_resource()
function initiates a check action on a specific resource.
The clsagfw_create_attr_iterator()
function creates an iterator to access all the attributes of the current resource.
clsagfwret clsagfw_create_attr_iterator(const clsagfw_aectx *pAeCtx, clsagfw_ai_flags flags);
pAeCtx
: Agent framework context pointer that is passed to entry points
flags
: CLSAGFW_ALL_ATTRS
: All attributes of the resource
CLSAGFW_MODIFIED_ATTRS
: Only modified attributes
Agents call this function to create an iterator to navigate through all the attributes of the resource. This is useful for agents managing multiple resources of different types. The iterator is an internal iterator maintained in the agent framework context. Each attribute is retrieved by calling the clsagfw_get_attr_from_iterator()
API. Modified attributes can be accessed only in the MODIFY entry point. At any given time, an entry point can create only one iterator. All subsequent attempts to create an iterator gets the pointer to the iterator that is already created.
The clsagfw_delete_cookie()
function deletes a cookie stored in the agent framework.
The clsagfw_exit2()
function terminates the agent process with resource retry feedback.
rid
: Resource ID of the resource causing the irrecoverable error
exitCode
: Process exit code
retry
: option to retry resource
An agent can encounter a irrecoverable error when executing an entry point for a resource and then must terminate the current process. An agent can use this API to end the agent process and provide feedback to the agent framework on the resource that is the cause for the irrecoverable error. If the retry parameter is set to true, then the current command on the resource is retried when the agent process restarts. If the parameter is set to false, then the current resource command is not retried and monitoring of the resource is disabled. This option can be used when a particular resource is the cause of repeated failures of an agent. The Oracle Clusterware server keeps track of the resources causing agent exits and automatically disables a resource if the failure rate is high. To re-enable a resource disabled due to high failure rate, must issue an explicit request to start the resource (for example, using CRSCTL).
The Oracle Clusterware server restarts the agent to continue monitoring resources managed by the agent.
The clsagfw_get_attr_from_iterator()
function returns the next attribute name and value from the created iterator.
The clsagfw_get_attrvalue()
function gets the value of an attribute of the current resource.
void clsagfw_get_attrvalue(const clsagfw_aectx *pAeCtx, const oratext *pAttrName, const oratext **pAttrValue);
The clsagfw_get_check_type()
function returns the type of the check command currently being executed.
The agent framework invokes the CHECK entry point of a resource for multiple conditions. By using this function, the agent can identify the exact condition for the current CHECK entry point and perform appropriate actions.
Possible conditions include:
CLSAGFW_INITIAL_CHECK: Check entry point invoked as part of the initial probe stage when the Oracle Clusterware server is started or restarted.
CLSAGFW_CHECK_AFTER_CMD: Check entry point invoked to follow up the prior action (such as start or stop) to determine the resultant resource state after the action execution.
CLSAGFW_PERIODIC_CHECK: Check entry point invoked by the agent framework at periodic intervals to monitor the state of a resource. The time interval is specified in the CHECK_INTERVAL
attribute of the resource.
CLSAGFW_EXTERNAL_CHECK: Check entry point invoked by agent framework when it receives an explicit check request from external entities, such as CRSCTL.
CLSAGFW_CHECKFROM_EP: Check action initiated by the agent itself by calling the clsagfw_check_resource()
API.
The clsagfw_get_cmdid()
function returns the type of the command for which the entry point is invoked.
The clsagfw_get_cookie()
function retrieves the value of a cookie stored in the agent framework.
The clsagfw_get_request_action_name()
function returns the name of the custom action to be executed on a resource.
The clsagfw_get_resource_id()
function retrieves the ID of the resource for which the entry point is being executed.
This function returns the Oracle Clusterware-generated resource ID. To retrieve the public display name of the resource, use the clsagfw_get_resource_name()
API.
The clsagfw_get_resource_name()
function retrieves the resource name of the current command.
The clsagfw_get_retry_count()
function returns the retry attempt number for the current command.
Agents can call this function in entrypoints to check if the current command is being retried. An agent process or Oracle Clusterware server process can terminate in the middle of executing a command on a resource. Oracle Clusterware retries the failed command when the agent or server process restarts. The command may have successfully or partially executed in the previous attempt. The agent can perform resume or clean up actions when Oracle Clusterware retries the command. The number of times a command can be retried is an internal parameter of Oracle Clusterware.
The clsagfw_get_type_name()
function retrieves the type name of the resource for which the entry point is being executed.
This function returns the Oracle Clusterware-generated resource ID. To retrieve the public display name of the resource, use the clsagfw_get_resource_name()
API.
The clsagfw_init()
function initializes the agent framework.
clsagfwret clsagfw_init(sb4 argc, oratext **argv, ub4 flags, const oratext *logName, void *reserved);
argc
: Number of command line arguments passed to the agent process
argv
: Command line arguments passed to the agent process
flags
:
logName
: Name of the log file for this agent
reserved
: Pass NULL
Oracle Clusterware automatically starts the agent configured for a resource when actions must be performed on the resource. On startup, the agent process calls this function first to initialize the agent framework run time. The command line arguments passed to the agent process by the Oracle Clusterware server must be passed to clsagfw_init()
. After initialization is complete, the agent can register resource types that are managed by the agent.
The clsagfw_is_cmd_timedout()
function returns the cause of the ABORT entry point.
The clsagfw_log()
function prints a diagnostic message to the agent log file.
void clsagfw_log(const clsagfw_aectx *pAeCtx, const ub4 log_level, const oratext *fmtp, ...);
pAeCtx
: Agent framework context that is passed to user entry points
log_level
: Log level of the message in the range of 1-5
fmtp
: Message format string, according to Standard C library print specifications
...
: Variable parameters corresponding to the format string
Agents call this function to log diagnostic messages that help in debugging and understanding agent execution. You can use the LOG_LEVEL
parameter to control the volume of log messages. You can configure the current logging level of a resource using CRSCTL, as follows:
$ crsctl set log level res "myResource1=3"
The misusages are logged to the agent log file in the TODO
directory. By default, the name of the log file is the same as the agent executable name. You can change this by passing the logName
parameter to the clsagfw_init()
API.
The clsagfw_modify_attribute()
function modifies an attribute of the current resource.
void clsagfw_modify_attribute(const clsagfw_aectx *pAeCtx, const oratext *pAttrName, const oratext *pAttrValue);
pAeCtx
: Agent framework context pointer that is passed to entry points
pAttrName
: Name of attribute to be modified
pAttrValue
: New value of attribute
Agents can modify the value of an attribute of the current command resource by calling this API. A resource modification request is sent to the Oracle Clusterware server for validation and the updated attribute value is reflected in the agent only after confirmation from the Oracle Clusterware server. This function can be only called from the START, STOP, and CLEAN entry points.
The clsagfw_reset_attr_iterator()
function resets the attribute iterator.
The clsagfw_send_status2()
function reports progress, warning, and error messages to the Oracle Clusterware server and the user.
void clsagfw_send_status2(const clsagfw_aectx* pAeCtx, const oratext* pResId, clsagfw_status_type type, const oratext* fmtp,...);
pAeCtx
: Agent framework context pointer that is passed to entry points
pResId
: Resource for which the message is being reported
type
: One of the following types of messages:
CLSAGFW_STATUS_PROGRESS
: Progress message
CLSAGFW_STATUS_WARNING
: Warning message
CLSAGFW_STATUS_ERROR
: Error message
fmtp
: Message format string
...
: Variables corresponding to positions in the message format string
The clsagfw_set_cookie()
function stores a cookie and its value in the agent framework.
The clsagfw_set_entrypoint()
function sets the C/C++ entry point function to be executed for a particular action on the resource.
void clsagfw_set_entrypoint(const oratext *type_name, clsagfw_action_entry action_entry, clsagfw_aecode action_entrycode)
The clsagfw_set_exitcb()
function registers a function to be called when the agent process exits.
typedef void (*clsagfw_exit_callback) (sb4 exitCode); void clsagfw_set_exitcb(clsagfw_exit_callback exit_func)
Agents can register a callback function to be invoked when the agent framework terminates the agent process. The callback function can perform proper clean up of any internal resources instantiated by the agent. If the agent process is exiting to recover from an irrecoverable error, then the Oracle Clusterware server does not restart the agent until the old incarnation has exited.
The clsagfw_set_resource_state_label()
function sets a custom label on the current resource.
The clsagfw_startup()
function starts the agent framework.
After the agent framework is initialized and the resource types and their entry points are registered, the agent calls this API to start the agent framework, which, in turn, starts the multithreaded infrastructure to monitor and perform actions on the resources.
On success, this function never returns to the calling thread. Entry points for the resource actions are invoked by the agent framework threads as and when required.
Example G-1 details an agent implementation to manage a resource that represents a file.
/* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. */ /* * NAME * Demoagent1.cpp: Demonstrates agent to monitor a file * * DESCRIPTION * This is a sample program that demonstrates an agent to monitor * a file. The agent has the following tasks: * - On startup : Create the file. * - On shutdown : Delete the file. * - On check command : Detect whether the file is present or not. * - On clean command : Delete the file. * This program can be used as a basis to build up more complicated * agents that manage real-world resources. * #include <stdlib.h> #include <stdio.h> #include <string.h> #include <clsagfw.h>
Include the agent framework clsagfw.h
header file.
#define TEST_TYPE1 (oratext *) "HOTFILE_TYPE" #define TEST_PATHNAME_ATTR (oratext *) "PATH_NAME" /* * NAME * test_agent_exit * DESCRIPTION * Function to clean up, called by framework whenever the agent * process is about to terminate * PARAMS * exitCode, which is an sb4 describing the reason for exit. * RETURNS * void */ void test_agent_exit(sb4 exitCode) { clsagfw_log(NULL, 1, (oratext *)"Demo Agent is exiting..\n"); }
Exit callback function registered with the agent framework.
/* * NAME * type1_start * DESCRIPTION * Action entry point for the 'start' command. Creates the file for * monitoring. * PARAMS * Pointer to the agent framework context * RETURNS * ub4 which could be CLSAGFW_AE_FAIL or CLSAGFW_AE_SUCCESS * depending on whether the action failed or succeeded. */ ub4 type1_start(const clsagfw_aectx *ectx) { ub4 ret = CLSAGFW_AE_FAIL; const oratext *pResName = NULL; const oratext *pPathName = NULL; FILE *fp; clsagfw_log(ectx, 1, (oratext *)"Start action called.."); /* Try to read the resource name */ if (clsagfw_get_attrvalue(ectx, (oratext *)"NAME", &pResName) != CLSAGFW_SUCCESS) { goto done; } /* Try to read the PATH_NAME attribute */ if (clsagfw_get_attrvalue(ectx, TEST_PATHNAME_ATTR, &pPathName) != CLSAGFW_SUCCESS) { goto done; }
Retrieve the resource name and the value of the PATH_NAME
attribute using clsagfw_get_attrvalue()
.
clsagfw_log(ectx, 1, (oratext *)"Start action arguments: resName = %s, pathName = %s", pResName, pPathName); /* Try to create the file */ fp = fopen((char *)pPathName, "w"); if(!fp) { /* Could not create the file */ clsagfw_log(ectx, 1, (oratext *) "START action for resource %s: FAILED\n", pResName); ret = CLSAGFW_AE_FAIL; } else { /* Created the file successfully */ clsagfw_log(ectx, 1, (oratext *) "START action for resource %s: SUCCESS\n", pResName); ret = CLSAGFW_AE_SUCCESS; fclose(fp); } done: return ret; }
Diagnostic and error messages are logged to the agent log file by calling clsagfw_log()
.
/* * NAME * type1_stop * DESCRIPTION * Action entry point for the 'stop' and 'clean' commands. Deletes * the file being monitored. * PARAMS * Pointer to agent framework context * RETURNS * ub4 which could be CLSAGFW_AE_FAIL or CLSAGFW_AE_SUCCESS * depending on whether the action failed or succeeded. */ ub4 type1_stop (const clsagfw_aectx *ectx) { ub4 ret = CLSAGFW_AE_FAIL; const oratext *pResName = NULL; const oratext *pPathName = NULL; clsagfw_log(ectx, 1, (oratext *)"Stop action called.."); /* Try to read the resource name */ if (clsagfw_get_attrvalue(ectx, (oratext *)"NAME", &pResName) != CLSAGFW_SUCCESS) { clsagfw_log(ectx, 1, (oratext *)"STOP action: %s: Could not read attribute\n", pResName); goto done; } /* Try to read the PATH_NAME attribute */ if (clsagfw_get_attrvalue(ectx, TEST_PATHNAME_ATTR, &pPathName) != CLSAGFW_SUCCESS) { pPathName = pResName; } clsagfw_log(ectx, 1, (oratext *)"Stop action arguments: resName = %s, pathName = %s", pResName, pPathName); /* Try to delete the file */ if (remove((char *)pPathName)) { /* Could not delete the file */ clsagfw_log(ectx, 1, (oratext *)"STOP action for resource %s: FAILED\n", pResName); ret = CLSAGFW_AE_FAIL; } else { /* Deleted the file successfully */ clsagfw_log(ectx, 1, (oratext *)"STOP action for resource %s: SUCCESS\n", pResName); ret = CLSAGFW_AE_SUCCESS; } done: return ret; } /* * NAME * type1_check * DESCRIPTION * Action entry point for the 'check' command. Determines if the * file exists. * PARAMS * Pointer to agent framework context. * RETURNS * ub4 which gives the status of the resource. Check the * agent framework reference for details on this function's * return codes. */ ub4 type1_check(const clsagfw_aectx *ectx) { ub4 ret = CLSAGFW_UNKNOWN; const oratext *pResName = NULL; const oratext *pPathName = NULL; FILE *fp; clsagfw_log(ectx, 1, (oratext *)"Check action called.."); /* Try to read the resource name */ if (clsagfw_get_attrvalue(ectx, (oratext *) "NAME", &pResName) != CLSAGFW_SUCCESS) { goto done; } /* Try to read the PATH_NAME attribute */ if (clsagfw_get_attrvalue(ectx, TEST_PATHNAME_ATTR, &pPathName) != CLSAGFW_SUCCESS) { clsagfw_log(ectx, 1, (oratext *)"CHECK action: %s: Could not read attribute\n", pResName); goto done; } clsagfw_log(ectx, 1, (oratext *)"Check action arguments: resName = %s, pathName = %s", pResName, pPathName); /* Check if the file is accessible */ fp = fopen((char *)pPathName, "r"); if (!fp) { /* Could not open file */ clsagfw_log(ectx, 1, (oratext *)"CHECK action: %s status – UNPLANNED_OFFLINE\n", pResName); ret = CLSAGFW_UNPLANNED_OFFLINE; } else { /* Opened file successfully */ clsagfw_log(ectx, 1,(oratext *)"CHECK action: %s status – ONLINE\n", pResName); fclose(fp); ret = CLSAGFW_ONLINE; } done: return ret; } /* * Initialization of the agent framework and registration of types is * done in main. */ int main(sb4 argc, oratext **argv) { clsagfw_log(NULL, 1, (oratext *)" *** Agent Framework Demo Agent Started *** \n"); /* * Initialize the agent framework */ if (clsagfw_init(argc, argv, 0, NULL, 0) != CLSAGFW_SUCCESS) { clsagfw_log(NULL, 1, (oratext *)"Failed to initilize the agent framework\n"); clsagfw_exit(-1); } /* * Set the exit callback function */ clsagfw_set_exitcb(test_agent_exit); /* * Add the type definition to the framework */ if (clsagfw_add_type(TEST_TYPE1) != CLSAGFW_SUCCESS) { clsagfw_log(NULL, 1,(oratext *)"Failed in adding type %s to the framework\n", TEST_TYPE1); clsagfw_exit(-1); } /* * Set all entry points for for HOTFILE_TYPE */ clsagfw_set_entrypoint(TEST_TYPE1, type1_start, CLSAGFW_ACTION_START); clsagfw_set_entrypoint(TEST_TYPE1, type1_stop, CLSAGFW_ACTION_STOP); clsagfw_set_entrypoint(TEST_TYPE1, type1_check, CLSAGFW_ACTION_CHECK); clsagfw_set_entrypoint(TEST_TYPE1, type1_stop, CLSAGFW_ACTION_CLEAN); clsagfw_log(NULL, 1, (oratext *)"Added resource type [%s] to the agent framework\n", TEST_TYPE1); /* * All set to go, Start the framework. This function does not * return if the framework starts successfully. */ clsagfw_startup(); /*** NOT REACHED **/ return 0; }