+
+struct ctdb_monitor_script_status {
+ struct ctdb_monitor_script_status *next;
+ const char *name;
+ struct timeval start;
+ struct timeval finished;
+ int32_t status;
+ int32_t timedout;
+ char *output;
+};
+
+struct ctdb_monitoring_status {
+ struct timeval start;
+ struct timeval finished;
+ int32_t status;
+ struct ctdb_monitor_script_status *scripts;
+};
+
+
+/* called from ctdb_logging when we have received output on STDERR from
+ * one of the eventscripts
+ */
+int ctdb_log_event_script_output(struct ctdb_context *ctdb, char *str, uint16_t len)
+{
+ struct ctdb_monitoring_status *monitoring_status =
+ talloc_get_type(ctdb->script_monitoring_ctx,
+ struct ctdb_monitoring_status);
+ struct ctdb_monitor_script_status *script;
+
+ if (monitoring_status == NULL) {
+ return -1;
+ }
+
+ script = monitoring_status->scripts;
+ if (script == NULL) {
+ return -1;
+ }
+
+ if (script->output == NULL) {
+ script->output = talloc_asprintf(script, "%*.*s", len, len, str);
+ } else {
+ script->output = talloc_asprintf_append(script->output, "%*.*s", len, len, str);
+ }
+
+ return 0;
+}
+
+/* called from the event script child process when we are starting a new
+ * monitor event
+ */
+int32_t ctdb_control_event_script_init(struct ctdb_context *ctdb)
+{
+ struct ctdb_monitoring_status *monitoring_status;
+
+ DEBUG(DEBUG_INFO, ("event script init called\n"));
+ if (ctdb->script_monitoring_ctx != NULL) {
+ talloc_free(ctdb->script_monitoring_ctx);
+ ctdb->script_monitoring_ctx = NULL;
+ }
+
+ monitoring_status = talloc_zero(ctdb, struct ctdb_monitoring_status);
+ if (monitoring_status == NULL) {
+ DEBUG(DEBUG_ERR, (__location__ " ERROR: Failed to talloc script_monitoring context\n"));
+ return -1;
+ }
+
+ ctdb->script_monitoring_ctx = monitoring_status;
+ monitoring_status->start = timeval_current();
+
+ return 0;
+}
+
+
+/* called from the event script child process when we are star running
+ * an eventscript
+ */
+int32_t ctdb_control_event_script_start(struct ctdb_context *ctdb, TDB_DATA indata)
+{
+ const char *name = (const char *)indata.dptr;
+ struct ctdb_monitoring_status *monitoring_status =
+ talloc_get_type(ctdb->script_monitoring_ctx,
+ struct ctdb_monitoring_status);
+ struct ctdb_monitor_script_status *script;
+
+ DEBUG(DEBUG_INFO, ("event script start called : %s\n", name));
+
+ if (monitoring_status == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " script_status is NULL when starting to run script %s\n", name));
+ return -1;
+ }
+
+ script = talloc_zero(monitoring_status, struct ctdb_monitor_script_status);
+ if (script == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " Failed to talloc ctdb_monitor_script_status for script %s\n", name));
+ return -1;
+ }
+
+ script->next = monitoring_status->scripts;
+ script->name = talloc_strdup(script, name);
+ script->start = timeval_current();
+ monitoring_status->scripts = script;
+
+ return 0;
+}
+
+/* called from the event script child process when we have finished running
+ * an eventscript
+ */
+int32_t ctdb_control_event_script_stop(struct ctdb_context *ctdb, TDB_DATA indata)
+{
+ int32_t res = *((int32_t *)indata.dptr);
+ struct ctdb_monitoring_status *monitoring_status =
+ talloc_get_type(ctdb->script_monitoring_ctx,
+ struct ctdb_monitoring_status);
+ struct ctdb_monitor_script_status *script;
+
+ DEBUG(DEBUG_INFO, ("event script stop called : %d\n", (int)res));
+
+ if (monitoring_status == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " script_status is NULL when script finished.\n"));
+ return -1;
+ }
+
+ script = monitoring_status->scripts;
+ if (script == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " script is NULL when the script had finished\n"));
+ return -1;
+ }
+
+ script->finished = timeval_current();
+ script->status = res;
+
+ return 0;
+}
+
+/* called from the event script child process when we have completed a
+ * monitor event
+ */
+int32_t ctdb_control_event_script_finished(struct ctdb_context *ctdb)
+{
+ struct ctdb_monitoring_status *monitoring_status =
+ talloc_get_type(ctdb->script_monitoring_ctx,
+ struct ctdb_monitoring_status);
+
+ DEBUG(DEBUG_INFO, ("event script finished called\n"));
+
+ if (monitoring_status == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " script_status is NULL when monitoring event finished\n"));
+ return -1;
+ }
+
+ monitoring_status->finished = timeval_current();
+ monitoring_status->status = MONITOR_SCRIPT_OK;
+ if (ctdb->last_monitoring_ctx) {
+ talloc_free(ctdb->last_monitoring_ctx);
+ }
+ ctdb->last_monitoring_ctx = ctdb->script_monitoring_ctx;
+ ctdb->script_monitoring_ctx = NULL;
+
+ return 0;
+}
+
+static struct ctdb_monitoring_wire *marshall_monitoring_scripts(TALLOC_CTX *mem_ctx, struct ctdb_monitoring_wire *monitoring_scripts, struct ctdb_monitor_script_status *script)
+{
+ struct ctdb_monitoring_script_wire script_wire;
+ size_t size;
+
+ if (script == NULL) {
+ return monitoring_scripts;
+ }
+ monitoring_scripts = marshall_monitoring_scripts(mem_ctx, monitoring_scripts, script->next);
+ if (monitoring_scripts == NULL) {
+ return NULL;
+ }
+
+ bzero(&script_wire, sizeof(struct ctdb_monitoring_script_wire));
+ strncpy(script_wire.name, script->name, MAX_SCRIPT_NAME);
+ script_wire.start = script->start;
+ script_wire.finished = script->finished;
+ script_wire.status = script->status;
+ script_wire.timedout = script->timedout;
+ if (script->output != NULL) {
+ strncpy(script_wire.output, script->output, MAX_SCRIPT_OUTPUT);
+ }
+
+ size = talloc_get_size(monitoring_scripts);
+ monitoring_scripts = talloc_realloc_size(mem_ctx, monitoring_scripts, size + sizeof(struct ctdb_monitoring_script_wire));
+ if (monitoring_scripts == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " Failed to talloc_resize monitoring_scripts blob\n"));
+ return NULL;
+ }
+
+ memcpy(&monitoring_scripts->scripts[monitoring_scripts->num_scripts], &script_wire, sizeof(script_wire));
+ monitoring_scripts->num_scripts++;
+
+ return monitoring_scripts;
+}
+
+int32_t ctdb_control_get_event_script_status(struct ctdb_context *ctdb, TDB_DATA *outdata)
+{
+ struct ctdb_monitoring_status *monitoring_status =
+ talloc_get_type(ctdb->last_monitoring_ctx,
+ struct ctdb_monitoring_status);
+ struct ctdb_monitoring_wire *monitoring_scripts;
+
+ if (monitoring_status == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " last_monitor_ctx is NULL when reading status\n"));
+ return -1;
+ }
+
+ monitoring_scripts = talloc_size(outdata, offsetof(struct ctdb_monitoring_wire, scripts));
+ if (monitoring_scripts == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " failed to talloc monitoring_scripts structure\n"));
+ return -1;
+ }
+
+ monitoring_scripts->num_scripts = 0;
+ monitoring_scripts = marshall_monitoring_scripts(outdata, monitoring_scripts, monitoring_status->scripts);
+ if (monitoring_scripts == NULL) {
+ DEBUG(DEBUG_ERR,(__location__ " Monitoring scritps is NULL. can not return data to client\n"));
+ return -1;
+ }
+
+ outdata->dsize = talloc_get_size(monitoring_scripts);
+ outdata->dptr = (uint8_t *)monitoring_scripts;
+
+ return 0;
+}
+