/* Defines a parent class for a Pandora module. Copyright (C) 2006 Artica ST. Written by Esteban Sanchez. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pandora_module.h" #include "../pandora_strutils.h" #include "../pandora.h" using namespace Pandora; using namespace Pandora_Modules; using namespace Pandora_Strutils; /** * Creates a Pandora_Module. * * Initializes all attributes. The default interval is set to 1 loop. * * @param name Module name. */ Pandora_Module::Pandora_Module (string name) { this->module_name = name; this->executions = 0; this->module_interval = 1; this->module_timeout = 15000; this->max = 0; this->min = 0; this->has_limits = false; this->async = false; this->data_list = NULL; this->inventory_list = NULL; } /** * Virtual destructor of Pandora_Module. * * Should be redefined by child classes. */ Pandora_Module::~Pandora_Module () { this->cleanDataList (); } void Pandora_Module::cleanDataList () { Pandora_Data *data; list::iterator iter; if (this->data_list) { if (this->data_list->size () > 0) { iter = this->data_list->begin (); for (iter = this->data_list->begin (); iter != this->data_list->end (); iter++) { data = *iter; delete data; } } delete this->data_list; this->data_list = NULL; } if (this->inventory_list) { if (this->inventory_list->size () > 0) { iter = this->inventory_list->begin (); for (iter = this->inventory_list->begin (); iter != this->inventory_list->end (); iter++) { data = *iter; delete data; } } delete this->inventory_list; this->inventory_list = NULL; } } /** * Get the Module_Type from a string type. * * @param type String type. * * @return The Module_Type which represents the type. */ Module_Type Pandora_Module::parseModuleTypeFromString (string type) { if (type == module_generic_data_str) { return TYPE_GENERIC_DATA; } else if (type == module_generic_data_inc_str) { return TYPE_GENERIC_DATA_INC; } else if (type == module_generic_data_string_str) { return TYPE_GENERIC_DATA_STRING; } else if (type == module_generic_proc_str) { return TYPE_GENERIC_PROC; } else if (type == module_async_data_str) { return TYPE_ASYNC_DATA; } else if (type == module_async_proc_str) { return TYPE_ASYNC_PROC; } else if (type == module_async_string_str) { return TYPE_ASYNC_STRING; } else { return TYPE_0; } } /** * Get the Module_Kind from a string Kind. * * @param kind String Kind. * * @return The Module_Kind which represents the Kind. */ Module_Kind Pandora_Module::parseModuleKindFromString (string kind) { if (kind == module_exec_str) { return MODULE_EXEC; } else if (kind == module_proc_str) { return MODULE_PROC; } else if (kind == module_service_str) { return MODULE_SERVICE; } else if (kind == module_freedisk_str) { return MODULE_FREEDISK; } else if (kind == module_freedisk_percent_str) { return MODULE_FREEDISK_PERCENT; } else if (kind == module_freememory_str) { return MODULE_FREEMEMORY; } else if (kind == module_freememory_percent_str) { return MODULE_FREEMEMORY_PERCENT; } else if (kind == module_cpuusage_str) { return MODULE_CPUUSAGE; } else if (kind == module_inventory_str) { return MODULE_INVENTORY; } else if (kind == module_odbc_str) { return MODULE_ODBC; } else if (kind == module_logevent_str) { return MODULE_LOGEVENT; } else if (kind == module_wmiquery_str) { return MODULE_WMIQUERY; } else if (kind == module_perfcounter_str) { return MODULE_PERFCOUNTER; } else if (kind == module_tcpcheck_str) { return MODULE_TCPCHECK; } else if (kind == module_regexp_str) { return MODULE_REGEXP; } else if (kind == module_plugin_str) { return MODULE_PLUGIN; } else { return MODULE_0; } } /** * Get the name of the module. * * @return The name of the module. */ string Pandora_Module::getName () const { return this->module_name; } /** * Get the description of the module. * * @return The module description. */ string Pandora_Module::getDescription () const { return this->module_description; } /** * Get the module type in a human readable string. * * @return The module type.. */ string Pandora_Module::getTypeString () const { return this->module_type_str; } /** * Get the module type in a integer value. * * @return The module type in a integer value. */ Module_Type Pandora_Module::getTypeInt () const { return this->module_type; } /** * Get the kind of the module in a integer_value. * * @return The module kind in a integer value. */ Module_Kind Pandora_Module::getModuleKind () const { return this->module_kind; } /** * Get the output of the module. * * @return The module output in a string value. */ string Pandora_Module::getLatestOutput () const { return this->latest_output; } /** * Get the type of the module in a integer_value. * * @return The module type in a integer value. */ Module_Type Pandora_Module::getModuleType () const { return this->module_type; } /** * Get the module output. * * After running the module, this function will return the output, * based on the module_type and the interval. * * @return The output in a string. * * @exception Output_Error Throwed if the module_type is not correct. * @exception Value_Error Throwed when the output is not in * the interval range. */ string Pandora_Module::getDataOutput (Pandora_Data *data) { double value; if (this->module_type == TYPE_GENERIC_DATA_STRING || this->module_type == TYPE_ASYNC_STRING) { return data->getValue (); } try { value = Pandora_Strutils::strtodouble (data->getValue ()); } catch (Pandora_Strutils::Invalid_Conversion e) { pandoraLog ("Output error on module %s", this->module_name.c_str ()); throw Output_Error (); } if (this->has_limits) { if (value >= this->max || value <= this->min) { pandoraLog ("The returned value was not in the interval on module %s", this->module_name.c_str ()); throw Value_Error (); } } return trim (data->getValue ()); } /** * Set the output of the module. * * If the function is called more than once before calling getXML, the * output will be accumulated and added to a tag. * * @param output Output to add. */ void Pandora_Module::setOutput (string output) { Pandora_Data *data; if (this->data_list == NULL) this->data_list = new list (); data = new Pandora_Data (output, this->module_name); this->data_list->push_back (data); this->latest_output = output; } /** * Set the output of the module. * * If the function is called more than once before calling getXML, the * output will be accumulated and added to a tag. * * @param output Output to add. * @param system_time Timestamp. */ void Pandora_Module::setOutput (string output, SYSTEMTIME *system_time) { Pandora_Data *data; if (this->data_list == NULL) this->data_list = new list (); data = new Pandora_Data (output, system_time, this->module_name); this->data_list->push_back (data); } /** * Run the module and generates the output. * * It is used by the child classes to check the execution interval * value and increment the executions variable. * * @exception Interval_Not_Fulfilled Throwed when the execution * interval value indicates that the module doesn't have * to execute. */ 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 ()); this->executions++; has_output = false; throw Interval_Not_Fulfilled (); } /* Increment the executions after check. This is done to execute the first time */ this->executions++; has_output = true; } /** * Get the XML output of the value. * * The output is a element of the TinyXML library. A sample output of * a module is: * @verbatim Conexiones abiertas generic_data 5 Conexiones abiertas @endverbatim * * @return A pointer to the TiXmlElement if successful which has to be * freed by the caller. NULL if the XML could not be created. */ string Pandora_Module::getXml () { string module_xml, data_clean; Pandora_Data *data; pandoraDebug ("%s getXML begin", module_name.c_str ()); /* No data */ if (!this->has_output || this->data_list == NULL) { return ""; } /* Compose the module XML */ module_xml = "\n\tmodule_name; module_xml += "]]>\n\tmodule_type_str; module_xml += "]]>\n"; if (this->module_description != "") { module_xml += "\tmodule_description; module_xml += "]]>\n"; } /* Write module data */ if (this->data_list && this->data_list->size () > 1) { list::iterator iter; module_xml += "\t\n"; iter = this->data_list->begin (); for (iter = this->data_list->begin (); iter != this->data_list->end (); iter++) { data = *iter; try { data_clean = strreplace (this->getDataOutput (data), "%", "%%" ); } catch (Output_Error e) { continue; } module_xml += "\t\t\n\t\t\t\n\t\t\tgetTimestamp (); module_xml += "]]>\n\t\t\n"; } module_xml += "\t\n"; } else { data = data_list->front (); try { data_clean = strreplace (this->getDataOutput (data), "%", "%%" ); module_xml += "\t\n"; } catch (Output_Error e) { } } /* Close the module tag */ module_xml += "\n"; /* Clean up */ this->cleanDataList (); pandoraDebug ("%s getXML end", module_name.c_str ()); return module_xml; } /** * Set the max value the module can have. * * The range is closed, so the value is included. * * @param value Max value to set. */ void Pandora_Module::setMax (int value) { this->has_limits = true; this->max = value; } /** * Set the min value the module can have. * * The range is closed, so the value is included. * * @param value Min value to set. */ void Pandora_Module::setMin (int value) { this->has_limits = true; this->min = value; } /** * Set the async flag to the module. * * If a module is set to be async, it would try to works only when the * events happen. Note that not all the modules can work in async mode. * * @param async Flag to set. */ void Pandora_Module::setAsync (bool async) { this->async = async; } /** * Set the module type from a string type. * * @param type String type. */ void Pandora_Module::setType (string type) { this->module_type_str = type; this->module_type = parseModuleTypeFromString (type); } /** * Set the module kind from a string kind. * * @param kind String kind. */ void Pandora_Module::setKind (string kind) { this->module_kind_str = kind; this->module_kind = parseModuleKindFromString (kind); } /** * Set the interval execution. * * @param interval Interval between executions. */ void Pandora_Module::setInterval (int interval) { this->module_interval = interval; } /** * Set the execution timeout. * * @param timeout Execution timeout. */ void Pandora_Module::setTimeout (int timeout) { if (timeout < 0) { return; } /* WaitForSingleObject expects milliseconds */ this->module_timeout = timeout * 1000; } /** * Get the execution interval. * * @return The execution interval. */ int Pandora_Module::getInterval () { return this->module_interval; } /** * Get the execution timeout. * * @return The execution timeout. */ int Pandora_Module::getTimeout () { return this->module_timeout; } /** * Set the module description. * * @param description Description of the module. */ void Pandora_Module::setDescription (string description) { this->module_description = description; }