diff --git a/pandora_agents/win32/ChangeLog b/pandora_agents/win32/ChangeLog index b2d921c4fc..4bc58422ff 100644 --- a/pandora_agents/win32/ChangeLog +++ b/pandora_agents/win32/ChangeLog @@ -1,3 +1,11 @@ +2012-01-03 Ramon Novoa + + * pandora_windows_service.h, + modules/pandora_module.h, + modules/pandora_module_factory.cc, + modules/pandora_module.cc, + pandora_windows_service.cc: Added support for intensive modules. + 2011-12-14 Ramon Novoa * modules/pandora_module_perfcounter.cc, diff --git a/pandora_agents/win32/modules/pandora_module.cc b/pandora_agents/win32/modules/pandora_module.cc index 0ad6d77d8b..3ecab9e799 100644 --- a/pandora_agents/win32/modules/pandora_module.cc +++ b/pandora_agents/win32/modules/pandora_module.cc @@ -61,6 +61,10 @@ Pandora_Module::Pandora_Module (string name) { this->max_warning = ""; this->disabled = ""; this->min_ff_event = ""; + this->intensive_condition_list = NULL; + this->intensive_interval = 1; + this->timestamp = 0; + this->intensive_match = 0; } /** @@ -70,9 +74,9 @@ Pandora_Module::Pandora_Module (string name) { */ Pandora_Module::~Pandora_Module () { Condition *cond = NULL; - Precondition *precond = NULL; + Condition *precond = NULL; list::iterator iter; - list::iterator iter_pre; + list::iterator iter_pre; /* Clean data lists */ this->cleanDataList (); @@ -110,6 +114,23 @@ Pandora_Module::~Pandora_Module () { delete (this->condition_list); this->condition_list = NULL; } + + /* Clean intensive_condition list */ + if (this->intensive_condition_list != NULL && this->intensive_condition_list->size () > 0) { + iter = this->intensive_condition_list->begin (); + for (iter = this->intensive_condition_list->begin (); + iter != this->intensive_condition_list->end (); + iter++) { + /* Free regular expressions */ + cond = *iter; + if (cond->string_value != "") { + regfree (&(cond->regexp)); + } + delete (*iter); + } + delete (this->intensive_condition_list); + this->intensive_condition_list = NULL; + } /* Clean the module cron */ if (this->cron != NULL) { @@ -414,6 +435,7 @@ Pandora_Module::setOutput (string output, SYSTEMTIME *system_time) { */ void Pandora_Module::setNoOutput () { + this->cleanDataList (); this->has_output = false; } @@ -430,9 +452,8 @@ Pandora_Module::setNoOutput () { void Pandora_Module::run () { /* Check the interval */ - if (this->executions % this->module_interval != 0) { - pandoraDebug ("%s: Interval is not fulfilled", - this->module_name.c_str ()); + if (this->executions % this->intensive_interval != 0) { + pandoraDebug ("%s: Interval is not fulfilled", this->module_name.c_str ()); this->executions++; has_output = false; throw Interval_Not_Fulfilled (); @@ -489,12 +510,10 @@ Pandora_Module::getXml () { } /* Interval */ - if (this->module_interval > 1) { - module_interval << this->module_interval; - module_xml += "\t\n"; - } + module_interval << this->module_interval; + module_xml += "\t\n"; /* Min */ if (this->has_min) { @@ -752,6 +771,16 @@ Pandora_Module::setInterval (int interval) { this->module_interval = interval; } +/** + * Set the intensive interval. + * + * @param intensive_interval Intensive interval. + */ +void +Pandora_Module::setIntensiveInterval (int intensive_interval) { + this->intensive_interval = intensive_interval; +} + /** * Set the execution timeout. * @@ -778,6 +807,16 @@ Pandora_Module::getInterval () { return this->module_interval; } +/** + * Get the intensive interval. + * + * @return The intensive interval. + */ +int +Pandora_Module::getIntensiveInterval () { + return this->intensive_interval; +} + /** * Get the execution timeout. * @@ -819,75 +858,19 @@ Pandora_Module::getSave () { } /** - * Adds a new precondition to the module. - * - * @param precondition string. - */ -void -Pandora_Module::addPrecondition (string precondition) { - Precondition *precond; - char operation[256], string_value[1024], command[1024]; - - /* Create the precondition list if it does not exist */ - if (this->precondition_list == NULL) { - this->precondition_list = new list (); - } - - /* Create the new precondition */ - precond = new Precondition; - if (precond == NULL) { - return; - } - - precond->value_1 = 0; - precond->value_2 = 0; - - /* Numeric comparison */ - if (sscanf (precondition.c_str (), "%255s %lf %1023[^\n]s", operation, &(precond->value_1), command) == 3) { - precond->operation = operation; - precond->command = command; - precond->command = "cmd.exe /c \"" + precond->command + "\""; - this->precondition_list->push_back (precond); - return; - - /* Regular expression */ - } else if (sscanf (precondition.c_str (), "=~ %1023s %1023[^\n]s", string_value, command) == 2) { - precond->operation = "=~"; - precond->string_value = string_value; - precond->command = command; - if (regcomp (&(precond->regexp), string_value, 0) != 0) { - pandoraDebug ("Invalid regular expression %s", string_value); - delete (precond); - return; - } - this->precondition_list->push_back (precond); - - /* Interval */ - } else if (sscanf (precondition.c_str (), "(%lf , %lf) %1023[^\n]s", &(precond->value_1), &(precond->value_2), command) == 3) { - precond->operation = "()"; - precond->command = command; - this->precondition_list->push_back (precond); - } else { - pandoraDebug ("Invalid module condition: %s", precondition.c_str ()); - delete (precond); - return; - } -return; -} - -/** - * Adds a new condition to the module. + * Adds a new condition to a condition list. * * @param condition Condition string. + * @param condition_list Pointer to the condition list. */ void -Pandora_Module::addCondition (string condition) { +Pandora_Module::addGenericCondition (string condition, list **condition_list) { Condition *cond; char operation[256], string_value[1024], command[1024]; /* Create the condition list if it does not exist */ - if (this->condition_list == NULL) { - this->condition_list = new list (); + if (*condition_list == NULL) { + *condition_list = new list (); } /* Create the new condition */ @@ -902,7 +885,7 @@ Pandora_Module::addCondition (string condition) { if (sscanf (condition.c_str (), "%255s %lf %1023[^\n]s", operation, &(cond->value_1), command) == 3) { cond->operation = operation; cond->command = command; - this->condition_list->push_back (cond); + (*condition_list)->push_back (cond); /* Regular expression */ } else if (sscanf (condition.c_str (), "=~ %1023s %1023[^\n]s", string_value, command) == 2) { cond->operation = "=~"; @@ -913,14 +896,82 @@ Pandora_Module::addCondition (string condition) { delete (cond); return; } - this->condition_list->push_back (cond); + (*condition_list)->push_back (cond); /* Interval */ } else if (sscanf (condition.c_str (), "(%lf , %lf) %1023[^\n]s", &(cond->value_1), &(cond->value_2), command) == 3) { cond->operation = "()"; cond->command = command; - this->condition_list->push_back (cond); + (*condition_list)->push_back (cond); } else { - pandoraDebug ("Invalid module condition: %s", condition.c_str ()); + pandoraLog ("Invalid condition: %s", condition.c_str ()); + delete (cond); + return; + } +} + +/** + * Adds a new module condition. + * + * @param condition Condition string. + */ +void +Pandora_Module::addCondition (string condition) { + addGenericCondition (condition, &(this->condition_list)); +} + +/** + * Adds a new module pre-condition. + * + * @param condition Condition string. + */ +void +Pandora_Module::addPreCondition (string condition) { + addGenericCondition (condition, &(this->precondition_list)); +} + +/** + * Adds a new module intensive condition. + * + * @param condition Condition string. + */ +void +Pandora_Module::addIntensiveCondition (string condition) { + Condition *cond; + char operation[256], string_value[1024], command[1024]; + + /* Create the condition list if it does not exist */ + if (this->intensive_condition_list == NULL) { + this->intensive_condition_list = new list (); + } + + /* Create the new condition */ + cond = new Condition; + if (cond == NULL) { + return; + } + cond->value_1 = 0; + cond->value_2 = 0; + + /* Numeric comparison */ + if (sscanf (condition.c_str (), "%255s %lf", operation, &(cond->value_1)) == 2) { + cond->operation = operation; + (this->intensive_condition_list)->push_back (cond); + /* Regular expression */ + } else if (sscanf (condition.c_str (), "=~ %1023s", string_value) == 1) { + cond->operation = "=~"; + cond->string_value = string_value; + if (regcomp (&(cond->regexp), string_value, 0) != 0) { + pandoraDebug ("Invalid regular expression %s", string_value); + delete (cond); + return; + } + (this->intensive_condition_list)->push_back (cond); + /* Interval */ + } else if (sscanf (condition.c_str (), "(%lf , %lf)", &(cond->value_1), &(cond->value_2)) == 2) { + cond->operation = "()"; + (this->intensive_condition_list)->push_back (cond); + } else { + pandoraDebug ("Invalid intensive condition: %s", condition.c_str ()); delete (cond); return; } @@ -937,11 +988,10 @@ Pandora_Module::evaluatePreconditions () { SECURITY_ATTRIBUTES attributes; HANDLE out, new_stdout, out_read, job; string working_dir; - Precondition *precond = NULL; - float float_output; - list::iterator iter; + Condition *precond = NULL; + double double_output; + list::iterator iter; unsigned char run; - int exe = 1; string output; if (this->precondition_list != NULL && this->precondition_list->size () > 0) { @@ -1016,78 +1066,69 @@ Pandora_Module::evaluatePreconditions () { } ResumeThread (pi.hThread); - /*string output;*/ - int tickbase = GetTickCount(); - while ( (dwRet = WaitForSingleObject (pi.hProcess, 500)) != WAIT_ABANDONED ) { - PeekNamedPipe (out_read, buffer, BUFSIZE, &read, &avail, NULL); - if (avail > 0) { - ReadFile (out_read, buffer, BUFSIZE, &read, NULL); - buffer[read] = '\0'; - output += (char *) buffer; + /*string output;*/ + int tickbase = GetTickCount(); + while ( (dwRet = WaitForSingleObject (pi.hProcess, 500)) != WAIT_ABANDONED ) { + PeekNamedPipe (out_read, buffer, BUFSIZE, &read, &avail, NULL); + if (avail > 0) { + ReadFile (out_read, buffer, BUFSIZE, &read, NULL); + buffer[read] = '\0'; + output += (char *) buffer; + } + + try { + double_output = Pandora_Strutils::strtodouble (output); + } catch (Pandora_Strutils::Invalid_Conversion e) { + double_output = 0; + } + + if (dwRet == WAIT_OBJECT_0) { + break; + } else if(this->getTimeout() < GetTickCount() - tickbase) { + /* STILL_ACTIVE */ + TerminateProcess(pi.hThread, STILL_ACTIVE); + pandoraLog ("evaluatePreconditions: %s timed out (retcode: %d)", this->module_name.c_str (), STILL_ACTIVE); + break; } - - float_output = atof(output.c_str()); - - if (dwRet == WAIT_OBJECT_0) { - break; - } else if(this->getTimeout() < GetTickCount() - tickbase) { - /* STILL_ACTIVE */ - TerminateProcess(pi.hThread, STILL_ACTIVE); - pandoraLog ("evaluatePreconditions: %s timed out (retcode: %d)", this->module_name.c_str (), STILL_ACTIVE); - break; } - } - - GetExitCodeProcess (pi.hProcess, &retval); - - if (retval != 0) { - if (! TerminateJobObject (job, 0)) { - pandoraLog ("evaluatePreconditions: TerminateJobObject failed. (error %d)", - GetLastError ()); + + GetExitCodeProcess (pi.hProcess, &retval); + + if (retval != 0) { + if (! TerminateJobObject (job, 0)) { + pandoraLog ("evaluatePreconditions: TerminateJobObject failed. (error %d)", + GetLastError ()); + } + if (retval != STILL_ACTIVE) { + pandoraLog ("evaluatePreconditions: %s did not executed well (retcode: %d)", + this->module_name.c_str (), retval); + } + /* Close job, process and thread handles. */ + CloseHandle (job); + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + CloseHandle (new_stdout); + CloseHandle (out_read); + return 0; } - if (retval != STILL_ACTIVE) { - pandoraLog ("evaluatePreconditions: %s did not executed well (retcode: %d)", - this->module_name.c_str (), retval); - } + /* Close job, process and thread handles. */ CloseHandle (job); CloseHandle (pi.hProcess); CloseHandle (pi.hThread); + } + CloseHandle (new_stdout); CloseHandle (out_read); - return 0; - } - - /* Close job, process and thread handles. */ - CloseHandle (job); - CloseHandle (pi.hProcess); - CloseHandle (pi.hThread); - } - - CloseHandle (new_stdout); - CloseHandle (out_read); - - if ((precond->operation == ">" && float_output > precond->value_1) || - (precond->operation == "<" && float_output < precond->value_1) || - (precond->operation == "=" && float_output == precond->value_1) || - (precond->operation == "!=" && float_output != precond->value_1) || - (precond->operation == "=~" && regexec (&(precond->regexp), output.c_str(), 0, NULL, 0) == 0) || - (precond->operation == "()" && float_output > precond->value_1 && float_output < precond->value_2)){ - exe = 1; - } else { - exe = 0; - return exe; + + if (evaluateCondition (output, double_output, precond) != 0) { + return 0; } - - CloseHandle (pi.hProcess); - } -} - return exe; -} - + } + } - - + return 1; +} /** * Evaluates and executes module conditions. @@ -1129,13 +1170,8 @@ Pandora_Module::evaluateConditions () { iter++) { cond = *iter; run = 0; - if ((cond->operation == ">" && double_value > cond->value_1) || - (cond->operation == "<" && double_value < cond->value_1) || - (cond->operation == "=" && double_value == cond->value_1) || - (cond->operation == "!=" && double_value != cond->value_1) || - (cond->operation == "=~" && regexec (&(cond->regexp), string_value.c_str (), 0, NULL, 0) == 0) || - (cond->operation == "()" && double_value > cond->value_1 && double_value < cond->value_2)) { - + + if (evaluateCondition (string_value, double_value, cond) == 1) { /* Run the condition command */ ZeroMemory (&si, sizeof (si)); ZeroMemory (&pi, sizeof (pi)); @@ -1150,6 +1186,56 @@ Pandora_Module::evaluateConditions () { } } +/** + * Evaluates and executes intensive module conditions. + */ +int +Pandora_Module::evaluateIntensiveConditions () { + double double_value; + string string_value; + Condition *cond = NULL; + list::iterator iter; + PROCESS_INFORMATION pi; + STARTUPINFO si; + Pandora_Data *pandora_data = NULL; + regex_t regex; + + /* Not an intensive module */ + if (this->intensive_condition_list == NULL || this->intensive_condition_list->size () <= 0) { + return 1; + } + + /* No data */ + if ( (!this->has_output) || this->data_list == NULL) { + return 0; + } + + /* Get the module data */ + pandora_data = data_list->front (); + + /* Get the string value of the data */ + string_value = pandora_data->getValue (); + + /* Get the double value of the data */ + try { + double_value = Pandora_Strutils::strtodouble (string_value); + } catch (Pandora_Strutils::Invalid_Conversion e) { + double_value = 0; + } + + iter = this->intensive_condition_list->begin (); + for (iter = this->intensive_condition_list->begin (); + iter != this->intensive_condition_list->end (); + iter++) { + cond = *iter; + if (evaluateCondition (string_value, double_value, cond) == 0) { + return 0; + } + } + + return 1; +} + /** * Checks the module cron. Returns 1 if the module should run, 0 if not. * @@ -1280,6 +1366,8 @@ Pandora_Module::setCron (string cron_string) { /** * Sets the interval of the module cron. + * + * @param interval Module cron interval in seconds. */ void Pandora_Module::setCronInterval (int interval) { @@ -1289,3 +1377,80 @@ Pandora_Module::setCronInterval (int interval) { this->cron->interval = interval; } + +/** + * Evaluate a single condition. Returns 1 if the condition matches, 0 + * otherwise. + * + * @param string_value String value. + * @param double_value Double value. + * @param condition Pointer to the condition. + */ +int Pandora_Module::evaluateCondition (string string_value, double double_value, Condition *condition) { + if ((condition->operation == ">" && double_value > condition->value_1) || + (condition->operation == "<" && double_value < condition->value_1) || + (condition->operation == "=" && double_value == condition->value_1) || + (condition->operation == "!=" && double_value != condition->value_1) || + (condition->operation == "=~" && regexec (&(condition->regexp), string_value.c_str(), 0, NULL, 0) == 0) || + (condition->operation == "()" && double_value > condition->value_1 && double_value < condition->value_2)) { + return 1; + } + + return 0; +} + +/** + * Checks if a module has data. + * + * @return 1 if the module has data, 0 otherwise. + */ +int Pandora_Module::hasOutput () { + if (this->has_output == 1) { + return 1; + } + + return 0; +} + +/** + * Sets the module timestamp. + * + * @param timestamp Module timestamp in seconds. + */ +void +Pandora_Module::setTimestamp (time_t timestamp) { + this->timestamp = timestamp; +} + +/** + * Gets the module timestamp. + * + * @return Module timestamp in seconds. + */ +time_t +Pandora_Module::getTimestamp () { + return this->timestamp; +} + +/** + * Sets the value of intensive_match. + * + * @param intensive_match 0 or 1. + */ +void +Pandora_Module::setIntensiveMatch (unsigned char intensive_match) { + this->intensive_match = intensive_match; +} + +/** + * Gets the value of intensive_match. + * + * @return The value of intensive match. + */ +unsigned char +Pandora_Module::getIntensiveMatch () { + return this->intensive_match; +} + + + diff --git a/pandora_agents/win32/modules/pandora_module.h b/pandora_agents/win32/modules/pandora_module.h index 18e0ba16a2..af573596de 100644 --- a/pandora_agents/win32/modules/pandora_module.h +++ b/pandora_agents/win32/modules/pandora_module.h @@ -91,18 +91,6 @@ namespace Pandora_Modules { MODULE_SNMPGET /**< SNMP get module */ } Module_Kind; - /** - * Defines the structure that holds module preconditions. - */ - typedef struct { - double value_1; - double value_2; - string string_value; - string operation; - string command; - regex_t regexp; - } Precondition; - /** * Defines the structure that holds module conditions. */ @@ -182,8 +170,13 @@ namespace Pandora_Modules { Module_Kind module_kind; string save; list *condition_list; - list *precondition_list; + list *precondition_list; Cron *cron; + list *intensive_condition_list; + time_t timestamp; + unsigned char intensive_match; + int intensive_interval; + protected: @@ -233,7 +226,9 @@ namespace Pandora_Modules { parseModuleKindFromString (string kind); void setInterval (int interval); + void setIntensiveInterval (int intensive_interval); int getInterval (); + int getIntensiveInterval (); void setTimeout (int timeout); int getTimeout (); string getSave (); @@ -273,14 +268,23 @@ namespace Pandora_Modules { void setSave (string save); void exportDataOutput (); - void addPrecondition (); - void addCondition (string condition); - void addPrecondition (string precondition); + void addGenericCondition (string condition, list **condition_list); + void addCondition (string precondition); + void addPreCondition (string precondition); + void addIntensiveCondition (string intensivecondition); int evaluatePreconditions (); void evaluateConditions (); int checkCron (); void setCron (string cron_string); void setCronInterval (int interval); + int evaluateCondition (string string_value, double double_value, Condition *condition); + int evaluateIntensiveConditions (); + int hasOutput (); + void setTimestamp (time_t timestamp); + time_t getTimestamp (); + void setIntensiveMatch (unsigned char intensive_match); + unsigned char getIntensiveMatch (); + }; } diff --git a/pandora_agents/win32/modules/pandora_module_factory.cc b/pandora_agents/win32/modules/pandora_module_factory.cc index 7528560b75..4520ad1b85 100644 --- a/pandora_agents/win32/modules/pandora_module_factory.cc +++ b/pandora_agents/win32/modules/pandora_module_factory.cc @@ -18,6 +18,7 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "pandora_windows_service.h" #include "pandora_module_factory.h" #include "pandora_module.h" #include "pandora_module_exec.h" @@ -104,7 +105,8 @@ using namespace Pandora_Strutils; #define TOKEN_SNMPCOMMUNITY ("module_snmp_community ") #define TOKEN_SNMPAGENT ("module_snmp_agent ") #define TOKEN_SNMPOID ("module_snmp_oid ") -#define TOKEN_ADVANCEDOPTIONS ("module_advanced_options ") +#define TOKEN_ADVANCEDOPTIONS ("module_advanced_options ") +#define TOKEN_INTENSIVECONDITION ("module_intensive_condition ") string parseLine (string line, string token) { @@ -153,15 +155,14 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { string module_disabled, module_min_ff_event, module_noseekeof; string module_ping, module_ping_count, module_ping_timeout; string module_snmpget, module_snmp_version, module_snmp_community, module_snmp_agent, module_snmp_oid; - string module_advanced_options, module_cooked; + string module_advanced_options, module_cooked, module_intensive_condition; Pandora_Module *module; bool numeric; Module_Type type; long agent_interval; - list condition_list; - list precondition_list; - list::iterator condition_iter; - list::iterator precondition_iter; + list condition_list, precondition_list, intensive_condition_list; + list::iterator condition_iter, precondition_iter, intensive_condition_iter; + Pandora_Windows_Service *service = NULL; module_name = ""; module_type = ""; @@ -217,6 +218,7 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { module_snmp_oid = ""; module_advanced_options = ""; module_cooked = ""; + module_intensive_condition = ""; stringtok (tokens, definition, "\n"); @@ -419,6 +421,15 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { if (module_cooked == "") { module_cooked = parseLine (line, TOKEN_COOKED); } + if (module_intensive_condition == "") { + module_intensive_condition = parseLine (line, TOKEN_INTENSIVECONDITION); + + /* Queue the condition and keep looking for more */ + if (module_intensive_condition != "") { + intensive_condition_list.push_back (module_intensive_condition); + module_intensive_condition = ""; + } + } iter++; } @@ -556,13 +567,13 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { module->setAsync (true); } -/* Module precondition */ + /* Module precondition */ if (precondition_list.size () > 0) { precondition_iter = precondition_list.begin (); for (precondition_iter = precondition_list.begin (); precondition_iter != precondition_list.end (); precondition_iter++) { - module->addPrecondition (*precondition_iter); + module->addPreCondition (*precondition_iter); } } @@ -576,6 +587,35 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { } } + /* Set the module interval */ + if (module_interval != "") { + int interval; + + try { + interval = strtoint (module_interval); + module->setInterval (interval); + module->setIntensiveInterval (interval); + } catch (Invalid_Conversion e) { + pandoraLog ("Invalid interval value \"%s\" for module %s", + module_interval.c_str (), + module_name.c_str ()); + } + } + + /* Module intensive condition */ + if (intensive_condition_list.size () > 0) { + intensive_condition_iter = intensive_condition_list.begin (); + for (intensive_condition_iter = intensive_condition_list.begin (); + intensive_condition_iter != intensive_condition_list.end (); + intensive_condition_iter++) { + module->addIntensiveCondition (*intensive_condition_iter); + } + /* Adjust the module interval for non-intensive modules */ + } else { + service = Pandora_Windows_Service::getInstance (); + module->setIntensiveInterval (module->getInterval () * (service->getInterval () / service->getIntensiveInterval ())); + } + /* Module cron */ if (module_crontab != "") { module->setCron (module_crontab); @@ -643,19 +683,6 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { } } - if (module_interval != "") { - int interval; - - try { - interval = strtoint (module_interval); - module->setInterval (interval); - } catch (Invalid_Conversion e) { - pandoraLog ("Invalid interval value \"%s\" for module %s", - module_interval.c_str (), - module_name.c_str ()); - } - } - if (module_post_process != "") { module->setPostProcess (module_post_process); } diff --git a/pandora_agents/win32/pandora_windows_service.cc b/pandora_agents/win32/pandora_windows_service.cc index 303aaab915..9efb0ce341 100644 --- a/pandora_agents/win32/pandora_windows_service.cc +++ b/pandora_agents/win32/pandora_windows_service.cc @@ -73,10 +73,11 @@ Pandora_Windows_Service::setValues (const char * svc_name, this->modules = NULL; this->conf = NULL; this->interval = 60000; - this->transfer_interval = this->interval; - this->elapsed_transfer_time = 0; + this->timestamp = 0; + this->run_time = 0; this->udp_server = NULL; this->tentacle_proxy = false; + this->intensive_interval = 60000; } /** @@ -202,7 +203,7 @@ Pandora_Windows_Service::check_broker_agents(string *all_conf){ void Pandora_Windows_Service::pandora_init () { - string conf_file, interval, debug, transfer_interval, util_dir, path, env; + string conf_file, interval, debug, intensive_interval, util_dir, path, env; string udp_server_enabled, udp_server_port, udp_server_addr, udp_server_auth_addr; string name_agent, name; string proxy_mode, server_ip; @@ -210,8 +211,6 @@ Pandora_Windows_Service::pandora_init () { int pos, num; static unsigned char first_run = 1; - setPandoraDebug (true); - conf_file = Pandora::getPandoraInstallDir (); conf_file += "pandora_agent.conf"; @@ -223,6 +222,34 @@ Pandora_Windows_Service::pandora_init () { if (this->modules != NULL) { delete this->modules; } + + /* Get the interval value (in seconds) and set it to the service */ + interval = conf->getValue ("interval"); + intensive_interval = conf->getValue ("intensive_interval"); + + if (interval != "") { + try { + /* miliseconds */ + this->interval_sec = strtoint (interval); + this->interval = this->interval_sec * 1000; + } catch (Invalid_Conversion e) { + } + } + + // Set the intensive interval + if (intensive_interval != "") { + try { + /* miliseconds */ + this->intensive_interval = strtoint (intensive_interval) * 1000; + } catch (Invalid_Conversion e) { + } + } else { + this->intensive_interval = this->interval; + } + + this->setSleepTime (this->intensive_interval); + + // Read modules this->modules = new Pandora_Module_List (conf_file); delete []all_conf; @@ -232,35 +259,10 @@ Pandora_Windows_Service::pandora_init () { } name_agent = "PANDORA_AGENT=" + name; putenv(name_agent.c_str()); - - /* Get the interval value (in seconds) and set it to the service */ - interval = conf->getValue ("interval"); - transfer_interval = conf->getValue ("transfer_interval"); debug = conf->getValue ("debug"); setPandoraDebug (is_enabled (debug)); - - if (interval != "") { - try { - /* miliseconds */ - this->interval = strtoint (interval) * 1000; - } catch (Invalid_Conversion e) { - } - } - - if (transfer_interval == "") { - this->transfer_interval = this->interval; - } else { - try { - /* miliseconds */ - this->transfer_interval = strtoint (transfer_interval) * 1000; - } catch (Invalid_Conversion e) { - this->transfer_interval = this->interval; - } - } - - this->setSleepTime (this->interval); - + /*Check if proxy mode is set*/ proxy_mode = conf->getValue ("proxy_mode"); if (proxy_mode != "" && this->tentacle_proxy == false) { @@ -1382,21 +1384,13 @@ Pandora_Windows_Service::pandora_run_broker (string config) { string server_addr; int startup_delay = 0; static unsigned char delayed = 0; - int exe = 1; - int i; - + unsigned char data_flag = 0; + unsigned char intensive_match; + pandoraDebug ("Run begin"); conf = this->getConf (); - /* Sleep if a startup delay was specified */ - startup_delay = atoi (conf->getValue ("startup_delay").c_str ()) * 1000; - if (startup_delay > 0 && delayed == 0) { - delayed = 1; - pandoraLog ("Delaying startup %d miliseconds", startup_delay); - Sleep (startup_delay); - } - /* Check for configuration changes */ if (getPandoraDebug () == false) { if (this->checkConfig (config) == 1) { @@ -1407,8 +1401,6 @@ Pandora_Windows_Service::pandora_run_broker (string config) { server_addr = conf->getValue ("server_ip"); - execution_number++; - if (this->modules != NULL) { this->modules->goFirst (); @@ -1416,18 +1408,29 @@ Pandora_Windows_Service::pandora_run_broker (string config) { Pandora_Module *module; module = this->modules->getCurrentValue (); + + /* Check preconditions */ + if (module->evaluatePreconditions () == 0) { + pandoraDebug ("Preconditions not matched for module %s", module->getName ().c_str ()); + module->setNoOutput (); + this->modules->goNext (); + continue; + } - exe = module->evaluatePreconditions (); - if (exe == 0) { + /* Check preconditions */ + if (module->checkCron () == 0) { + pandoraDebug ("Cron not matched for module %s", module->getName ().c_str ()); module->setNoOutput (); this->modules->goNext (); continue; } pandoraDebug ("Run %s", module->getName ().c_str ()); - if (module->checkCron () == 1) { - module->run (); - Sleep(10); + module->run (); + if (! module->hasOutput ()) { + module->setNoOutput (); + this->modules->goNext (); + continue; } /* Save module data to an environment variable */ @@ -1435,22 +1438,37 @@ Pandora_Windows_Service::pandora_run_broker (string config) { module->exportDataOutput (); } + /* Evaluate intensive conditions */ + intensive_match = module->evaluateIntensiveConditions (); + if (intensive_match == module->getIntensiveMatch () && module->getTimestamp () + module->getInterval () * this->interval_sec > this->run_time) { + module->setNoOutput (); + this->modules->goNext (); + continue; + } + module->setIntensiveMatch (intensive_match); + + if (module->getTimestamp () + module->getInterval () * this->interval_sec <= this->run_time) { + module->setTimestamp (this->run_time); + } + /* Evaluate module conditions */ module->evaluateConditions (); + + /* At least one module has data */ + data_flag = 1; this->modules->goNext (); } } - -this->elapsed_transfer_time += this->interval; - -if (this->elapsed_transfer_time >= this->transfer_interval) { - this->elapsed_transfer_time = 0; - if (!server_addr.empty ()) { + + if (data_flag == 1 || this->timestamp + this->interval_sec <= this->run_time) { - this->sendXml (this->modules); + // Send the XML + if (!server_addr.empty ()) { + this->sendXml (this->modules); + } } -} + return; } @@ -1458,23 +1476,27 @@ void Pandora_Windows_Service::pandora_run () { Pandora_Agent_Conf *conf = NULL; string server_addr, conf_file, *all_conf; - int startup_delay = 0; - static unsigned char delayed = 0; - int exe = 1; - int i, num; - + int startup_delay = 0; + int i, num; + static unsigned char delayed = 0; + unsigned char data_flag = 0; + unsigned char intensive_match; + pandoraDebug ("Run begin"); conf = this->getConf (); - + /* Sleep if a startup delay was specified */ startup_delay = atoi (conf->getValue ("startup_delay").c_str ()) * 1000; - if (startup_delay > 0 && delayed == 0) { + if (startup_delay > 0 && delayed == 0) { delayed = 1; - pandoraLog ("Delaying startup %d miliseconds", startup_delay); - Sleep (startup_delay); - } + pandoraLog ("Delaying startup %d miliseconds", startup_delay); + Sleep (startup_delay); + } + /* Set the run time */ + this->run_time = time (NULL); + /* Check for configuration changes */ if (getPandoraDebug () == false) { conf_file = Pandora::getPandoraInstallDir (); @@ -1498,17 +1520,28 @@ Pandora_Windows_Service::pandora_run () { module = this->modules->getCurrentValue (); - exe = module->evaluatePreconditions (); - if (exe == 0) { + /* Check preconditions */ + if (module->evaluatePreconditions () == 0) { + pandoraDebug ("Preconditions not matched for module %s", module->getName ().c_str ()); module->setNoOutput (); this->modules->goNext (); continue; } + /* Check preconditions */ + if (module->checkCron () == 0) { + pandoraDebug ("Cron not matched for module %s", module->getName ().c_str ()); + module->setNoOutput (); + this->modules->goNext (); + continue; + } + pandoraDebug ("Run %s", module->getName ().c_str ()); - if (module->checkCron () == 1) { - module->run (); - Sleep(5); + module->run (); + if (! module->hasOutput ()) { + module->setNoOutput (); + this->modules->goNext (); + continue; } /* Save module data to an environment variable */ @@ -1516,25 +1549,39 @@ Pandora_Windows_Service::pandora_run () { module->exportDataOutput (); } + /* Evaluate intensive conditions */ + intensive_match = module->evaluateIntensiveConditions (); + if (intensive_match == module->getIntensiveMatch () && module->getTimestamp () + module->getInterval () * this->interval_sec > this->run_time) { + module->setNoOutput (); + this->modules->goNext (); + continue; + } + module->setIntensiveMatch (intensive_match); + + if (module->getTimestamp () + module->getInterval () * this->interval_sec <= this->run_time) { + module->setTimestamp (this->run_time); + } + /* Evaluate module conditions */ module->evaluateConditions (); + + /* At least one module has data */ + data_flag = 1; this->modules->goNext (); } } - this->elapsed_transfer_time += this->interval; - - if (this->elapsed_transfer_time >= this->transfer_interval) { - this->elapsed_transfer_time = 0; + if (data_flag == 1 || this->timestamp + this->interval_sec <= this->run_time) { + + // Send the XML if (!server_addr.empty ()) { - this->sendXml (this->modules); } } /* Get the interval value (in minutes) */ - pandoraDebug ("Next execution on %d seconds", this->interval / 1000); + pandoraDebug ("Next execution on %d seconds", this->interval_sec); /* Load and execute brokers */ num = count_broker_agents(); @@ -1551,6 +1598,11 @@ Pandora_Windows_Service::pandora_run () { pandora_init (); } + /* Reset time reference if necessary */ + if (this->timestamp + this->interval_sec <= this->run_time) { + this->timestamp = this->run_time; + } + return; } @@ -1558,3 +1610,14 @@ Pandora_Agent_Conf * Pandora_Windows_Service::getConf () { return this->conf; } + +long +Pandora_Windows_Service::getInterval () { + return this->interval; +} + +long +Pandora_Windows_Service::getIntensiveInterval () { + return this->intensive_interval; +} + diff --git a/pandora_agents/win32/pandora_windows_service.h b/pandora_agents/win32/pandora_windows_service.h index 266a8f0b03..99977107dc 100644 --- a/pandora_agents/win32/pandora_windows_service.h +++ b/pandora_agents/win32/pandora_windows_service.h @@ -22,6 +22,7 @@ #define __PANDORA_WINDOWS_SERVICE_H__ #include +#include #include "windows_service.h" #include "pandora_agent_conf.h" #include "modules/pandora_module_list.h" @@ -43,8 +44,8 @@ namespace Pandora { Pandora_Module_List *modules; long execution_number; string agent_name; - long elapsed_transfer_time; - long transfer_interval; + time_t timestamp; + time_t run_time; bool started; void *udp_server; bool tentacle_proxy; @@ -91,6 +92,8 @@ namespace Pandora { void pandora_init (); long interval; + long interval_sec; + long intensive_interval; public: static Pandora_Windows_Service *getInstance (); @@ -101,9 +104,12 @@ namespace Pandora { const char *svc_description); void start (); - int sendXml (Pandora_Module_List *modules); - void sendBufferedXml (string path); - Pandora_Agent_Conf *getConf (); + int sendXml (Pandora_Module_List *modules); + void sendBufferedXml (string path); + Pandora_Agent_Conf *getConf (); + long getInterval (); + long getIntensiveInterval (); + }; }