2008-12-03 Esteban Sanchez <estebans@artica.es>

* pandora.[cc,h]: Function is_enabled() was moved here to be
	accesible.

	* pandora_windows_service.cc: Removed is_enabled() private function.

	* windows_service.cc: Service is now interactive, so it can open
	interactive processes in the watchdog mode of proc modules.

	* modules/pandora_module_factory.cc: Added "module_watchdog" and
	"module_start_command" tokens to service and process modules. Style
	correction.

	* modules/pandora_module_proc.[cc,h]: Added watchdog mode to run
	proccess when they die. It's done by setting a start command to
	recover it.

	* modules/pandora_module_service.[cc,h]: Added watchdog mode to start
	a service when it's stopped.



git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@1277 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
esanchezm 2008-12-03 12:04:48 +00:00
parent 3fe199fbe7
commit dfb6467cb5
13 changed files with 354 additions and 105 deletions

View File

@ -1,3 +1,24 @@
2008-12-03 Esteban Sanchez <estebans@artica.es>
* pandora.[cc,h]: Function is_enabled() was moved here to be
accesible.
* pandora_windows_service.cc: Removed is_enabled() private function.
* windows_service.cc: Service is now interactive, so it can open
interactive processes in the watchdog mode of proc modules.
* modules/pandora_module_factory.cc: Added "module_watchdog" and
"module_start_command" tokens to service and process modules. Style
correction.
* modules/pandora_module_proc.[cc,h]: Added watchdog mode to run
proccess when they die. It's done by setting a start command to
recover it.
* modules/pandora_module_service.[cc,h]: Added watchdog mode to start
a service when it's stopped.
2008-12-01 Ramon Novoa <rnovoa@artica.es> 2008-12-01 Ramon Novoa <rnovoa@artica.es>
* windows/pandora_wmi.cc, * windows/pandora_wmi.cc,

View File

@ -101,9 +101,8 @@ namespace Pandora_Modules {
* The module does not satisfy its interval. * The module does not satisfy its interval.
*/ */
class Interval_Not_Fulfilled : public Pandora_Modules::Module_Exception { }; class Interval_Not_Fulfilled : public Pandora_Modules::Module_Exception { };
/** /** * Pandora module super-class.
* Pandora module super-class.
* *
* Every defined module must inherit of this class. * Every defined module must inherit of this class.
*/ */

View File

@ -35,26 +35,28 @@ using namespace Pandora;
using namespace Pandora_Modules; using namespace Pandora_Modules;
using namespace Pandora_Strutils; using namespace Pandora_Strutils;
#define TOKEN_NAME ("module_name ") #define TOKEN_NAME ("module_name ")
#define TOKEN_TYPE ("module_type ") #define TOKEN_TYPE ("module_type ")
#define TOKEN_INTERVAL ("module_interval ") #define TOKEN_INTERVAL ("module_interval ")
#define TOKEN_EXEC ("module_exec ") #define TOKEN_EXEC ("module_exec ")
#define TOKEN_PROC ("module_proc ") #define TOKEN_PROC ("module_proc ")
#define TOKEN_SERVICE ("module_service ") #define TOKEN_SERVICE ("module_service ")
#define TOKEN_FREEDISK ("module_freedisk ") #define TOKEN_FREEDISK ("module_freedisk ")
#define TOKEN_FREEMEMORY ("module_freememory") #define TOKEN_FREEMEMORY ("module_freememory")
#define TOKEN_CPUUSAGE ("module_cpuusage ") #define TOKEN_CPUUSAGE ("module_cpuusage ")
#define TOKEN_ODBC ("module_odbc ") #define TOKEN_ODBC ("module_odbc ")
#define TOKEN_MAX ("module_max ") #define TOKEN_MAX ("module_max ")
#define TOKEN_MIN ("module_min ") #define TOKEN_MIN ("module_min ")
#define TOKEN_DESCRIPTION ("module_description ") #define TOKEN_DESCRIPTION ("module_description ")
#define TOKEN_ODBC_QUERY ("module_odbc_query ") #define TOKEN_ODBC_QUERY ("module_odbc_query ")
#define TOKEN_LOGEVENT ("module_logevent") #define TOKEN_LOGEVENT ("module_logevent")
#define TOKEN_SOURCE ("module_source ") #define TOKEN_SOURCE ("module_source ")
#define TOKEN_EVENTTYPE ("module_eventtype ") #define TOKEN_EVENTTYPE ("module_eventtype ")
#define TOKEN_EVENTCODE ("module_eventcode ") #define TOKEN_EVENTCODE ("module_eventcode ")
#define TOKEN_PATTERN ("module_pattern ") #define TOKEN_PATTERN ("module_pattern ")
#define TOKEN_ASYNC ("module_async") #define TOKEN_ASYNC ("module_async")
#define TOKEN_WATCHDOG ("module_watchdog ")
#define TOKEN_START_COMMAND ("module_start_command ")
string string
parseLine (string line, string token) { parseLine (string line, string token) {
@ -90,28 +92,32 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
string module_freedisk, module_cpuusage, module_odbc; string module_freedisk, module_cpuusage, module_odbc;
string module_odbc_query, module_dsn, module_freememory; string module_odbc_query, module_dsn, module_freememory;
string module_logevent, module_source, module_eventtype, module_eventcode; string module_logevent, module_source, module_eventtype, module_eventcode;
string module_pattern, module_async; string module_pattern, module_async;
string module_watchdog, module_start_command;
Pandora_Module *module; Pandora_Module *module;
bool numeric; bool numeric;
Module_Type type; Module_Type type;
module_name = ""; module_name = "";
module_type = ""; module_type = "";
module_min = ""; module_min = "";
module_max = ""; module_max = "";
module_description = ""; module_description = "";
module_interval = ""; module_interval = "";
module_exec = ""; module_exec = "";
module_proc = ""; module_proc = "";
module_service = ""; module_service = "";
module_odbc = ""; module_odbc = "";
module_odbc_query = ""; module_odbc_query = "";
module_odbc = ""; module_odbc = "";
module_logevent = ""; module_logevent = "";
module_source = ""; module_source = "";
module_eventtype = ""; module_eventtype = "";
module_eventcode = ""; module_eventcode = "";
module_pattern = ""; module_pattern = "";
module_async = "";
module_watchdog = "";
module_start_command = "";
stringtok (tokens, definition, "\n"); stringtok (tokens, definition, "\n");
@ -182,6 +188,12 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
if (module_async == "") { if (module_async == "") {
module_async = parseLine (line, TOKEN_ASYNC); module_async = parseLine (line, TOKEN_ASYNC);
} }
if (module_start_command == "") {
module_start_command = parseLine (line, TOKEN_START_COMMAND);
}
if (module_watchdog == "") {
module_watchdog = parseLine (line, TOKEN_WATCHDOG);
}
iter++; iter++;
} }
@ -192,10 +204,36 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
module_exec); module_exec);
} else if (module_proc != "") { } else if (module_proc != "") {
module = new Pandora_Module_Proc (module_name, module = new Pandora_Module_Proc (module_name,
module_proc); module_proc);
if (module_watchdog != "") {
bool enabled;
enabled = is_enabled (module_watchdog);
if (enabled) {
if (module_start_command == "") {
pandoraLog ("Module \"%s\" is marked to be watchdog but no recover command was set. "
"Please add a new token 'module_start_command c:\\command_to_recover.exe'",
module_name.c_str ());
delete module;
return NULL;
}
Pandora_Module_Proc *module_proc;
module_proc = (Pandora_Module_Proc *) module;
module_proc->setWatchdog (true);
module_proc->setStartCommand (module_start_command);
}
}
} else if (module_service != "") { } else if (module_service != "") {
module = new Pandora_Module_Service (module_name, module = new Pandora_Module_Service (module_name,
module_service); module_service);
if (module_watchdog != "") {
Pandora_Module_Service *module_service;
module_service = (Pandora_Module_Service *) module;
module_service->setWatchdog (is_enabled (module_watchdog));
}
} else if (module_freedisk != "") { } else if (module_freedisk != "") {
module = new Pandora_Module_Freedisk (module_name, module = new Pandora_Module_Freedisk (module_name,
module_freedisk); module_freedisk);
@ -221,10 +259,10 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
module_odbc_query); module_odbc_query);
} else if (module_logevent != "") { } else if (module_logevent != "") {
module = new Pandora_Module_Logevent (module_name, module = new Pandora_Module_Logevent (module_name,
module_source, module_source,
module_eventtype, module_eventtype,
module_eventcode, module_eventcode,
module_pattern); module_pattern);
} else { } else {
return NULL; return NULL;
} }
@ -296,6 +334,7 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
module_interval.c_str (), module_interval.c_str (),
module_name.c_str ()); module_name.c_str ());
} }
} }
return module; return module;
} }

View File

@ -45,7 +45,10 @@ Pandora_Module_Proc::Pandora_Module_Proc (string name, string process_name)
transform (process_name.begin (), process_name.end (), transform (process_name.begin (), process_name.end (),
this->process_name.begin (), (int (*) (int)) tolower); this->process_name.begin (), (int (*) (int)) tolower);
this->setKind (module_proc_str); this->setKind (module_proc_str);
this->watchdog = false;
this->start_command = "";
} }
string string
@ -53,6 +56,26 @@ Pandora_Module_Proc::getProcessName () const {
return this->process_name; return this->process_name;
} }
bool
Pandora_Module_Proc::isWatchdog () const {
return this->watchdog;
}
string
Pandora_Module_Proc::getStartCommand () const {
return this->start_command;
}
void
Pandora_Module_Proc::setWatchdog (bool watchdog) {
this->watchdog = watchdog;
}
void
Pandora_Module_Proc::setStartCommand (string command) {
this->start_command = command;
}
void void
async_run (Pandora_Module_Proc *module) { async_run (Pandora_Module_Proc *module) {
HANDLE *processes = NULL; HANDLE *processes = NULL;
@ -72,6 +95,9 @@ async_run (Pandora_Module_Proc *module) {
while (1) { while (1) {
processes = getProcessHandles (module->getProcessName ()); processes = getProcessHandles (module->getProcessName ());
if (processes == NULL) { if (processes == NULL) {
if (module->isWatchdog ()) {
Pandora_Wmi::runProgram (module->getStartCommand ());
}
Sleep (2000); Sleep (2000);
continue; continue;
} }
@ -106,6 +132,10 @@ async_run (Pandora_Module_Proc *module) {
Pandora_Windows_Service::getInstance ()->sendXml (modules); Pandora_Windows_Service::getInstance ()->sendXml (modules);
} }
if (res == 0 && module->isWatchdog ()) {
Pandora_Wmi::runProgram (module->getStartCommand ());
}
/* Free handles */ /* Free handles */
for (i = 0; i < nprocess; i++) for (i = 0; i < nprocess; i++)
CloseHandle (processes[i]); CloseHandle (processes[i]);

View File

@ -30,13 +30,20 @@ namespace Pandora_Modules {
class Pandora_Module_Proc : public Pandora_Module { class Pandora_Module_Proc : public Pandora_Module {
private: private:
string process_name; string process_name;
HANDLE thread; HANDLE thread;
bool watchdog;
string start_command;
public: public:
Pandora_Module_Proc (string name, string process_name); Pandora_Module_Proc (string name, string process_name);
string getProcessName () const; string getProcessName () const;
string getStartCommand () const;
bool isWatchdog () const;
void setWatchdog (bool watchdog);
void setStartCommand (string command);
void run (); void run ();
}; };
} }

View File

@ -46,7 +46,8 @@ Pandora_Module_Service::Pandora_Module_Service (string name, string service_name
this->service_name.begin (), (int (*) (int)) tolower); this->service_name.begin (), (int (*) (int)) tolower);
this->setKind (module_service_str); this->setKind (module_service_str);
this->thread = 0; this->thread = 0;
this->watchdog = false;
} }
string string
@ -54,6 +55,17 @@ Pandora_Module_Service::getServiceName () const {
return this->service_name; return this->service_name;
} }
bool
Pandora_Module_Service::isWatchdog () const {
return this->watchdog;
}
void
Pandora_Module_Service::setWatchdog (bool watchdog) {
this->watchdog = watchdog;
}
#define BUFFER_SIZE (16384) #define BUFFER_SIZE (16384)
void void
@ -107,8 +119,8 @@ async_run (Pandora_Module_Service *module) {
continue; continue;
event_id = record->EventID & 0x0000ffff; event_id = record->EventID & 0x0000ffff;
/* Those numbers are the code for service start/stopping */ /* This number is the code for service start/stopping */
if (event_id == 7035 || event_id == 7036) { if (event_id == 7036) {
service_event = true; service_event = true;
break; break;
} }
@ -123,6 +135,10 @@ async_run (Pandora_Module_Service *module) {
prev_res = str_res; prev_res = str_res;
Pandora_Windows_Service::getInstance ()->sendXml (modules); Pandora_Windows_Service::getInstance ()->sendXml (modules);
} }
if (res == 0 && module->isWatchdog ()) {
Pandora_Wmi::startService (module->getServiceName ());
}
} }
CloseHandle (event); CloseHandle (event);
CloseEventLog (event_log); CloseEventLog (event_log);

View File

@ -32,12 +32,16 @@ namespace Pandora_Modules {
class Pandora_Module_Service : public Pandora_Module { class Pandora_Module_Service : public Pandora_Module {
private: private:
string service_name; string service_name;
HANDLE thread; HANDLE thread;
bool watchdog;
public: public:
Pandora_Module_Service (string name, string service_name); Pandora_Module_Service (string name, string service_name);
void run (); void run ();
string getServiceName () const; string getServiceName () const;
bool isWatchdog () const;
void setWatchdog (bool watchdog);
}; };
} }

View File

@ -272,3 +272,22 @@ string
Pandora::getPandoraAgentVersion () { Pandora::getPandoraAgentVersion () {
return pandora_version; return pandora_version;
} }
bool
Pandora::is_enabled (string value) {
static string enabled_values[] = {"enabled", "1", "on", "yes", "si", "", "ok", "true", ""};
int i = 0;
if (value == "") {
return false;
}
while (enabled_values[i] != "") {
if (enabled_values[i] == value) {
return true;
}
i++;
}
return false;
}

View File

@ -66,7 +66,8 @@ namespace Pandora {
void pandoraDebug (char *format, ...); void pandoraDebug (char *format, ...);
void pandoraLog (char *format, ...); void pandoraLog (char *format, ...);
void pandoraFree (void * e); void pandoraFree (void * e);
bool is_enabled (string value);
/** /**
* Super-class exception. * Super-class exception.
* *

View File

@ -37,8 +37,6 @@ using namespace std;
using namespace Pandora; using namespace Pandora;
using namespace Pandora_Modules; using namespace Pandora_Modules;
using namespace Pandora_Strutils; using namespace Pandora_Strutils;
string enabled_values[] = {"enabled", "1", "on", "yes", "si", "", "ok", ""};
Pandora_Windows_Service::Pandora_Windows_Service () Pandora_Windows_Service::Pandora_Windows_Service ()
: Windows_Service (NULL, NULL, NULL) { : Windows_Service (NULL, NULL, NULL) {
@ -101,23 +99,6 @@ Pandora_Windows_Service::getInstance () {
void void
Pandora_Windows_Service::start () { Pandora_Windows_Service::start () {
this->started = true; this->started = true;
}
bool
is_enabled (string value) {
int i = 0;
if (value == "") {
return false;
}
while (enabled_values[i] != "") {
if (enabled_values[i] == value) {
return true;
}
i++;
}
return false;
} }
void void

View File

@ -25,17 +25,18 @@
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <sstream> #include <sstream>
#include <ctime> #include <ctime>
#include <winuser.h>
using namespace std; using namespace std;
using namespace Pandora_Wmi; using namespace Pandora_Wmi;
static LPWSTR static LPWSTR
getWmiStr (LPCWSTR computer) { getWmiStr (LPCWSTR computer) {
static WCHAR wmi_str [256]; static WCHAR wmi_str[256];
wcscpy (wmi_str, L"winmgmts:{impersonationLevel=impersonate}!\\\\");
wcscpy (wmi_str, L"winmgmts:\\\\");
if (computer) { if (computer) {
wcsncat (wmi_str, computer, 128); wcsncat (wmi_str, computer, 128);
} else { } else {
@ -43,7 +44,7 @@ getWmiStr (LPCWSTR computer) {
} }
wcscat (wmi_str, L"\\root\\cimv2"); wcscat (wmi_str, L"\\root\\cimv2");
return wmi_str; return wmi_str;
} }
@ -388,7 +389,9 @@ Pandora_Wmi::getSystemName () {
* @return The list of events. * @return The list of events.
*/ */
void void
Pandora_Wmi::getEventList (string source, string type, string code, string pattern, int interval, list<string> &event_list) { Pandora_Wmi::getEventList (string source, string type, string code,
string pattern, int interval,
list<string> &event_list) {
CDhInitialize init; CDhInitialize init;
CDispPtr wmi_svc, quickfixes; CDispPtr wmi_svc, quickfixes;
char *value = NULL; char *value = NULL;
@ -453,8 +456,8 @@ Pandora_Wmi::getEventList (string source, string type, string code, string patte
*/ */
string string
Pandora_Wmi::getTimestampLimit (int interval) { Pandora_Wmi::getTimestampLimit (int interval) {
char limit_str[26], diff_sign; char limit_str[26], diff_sign;
time_t limit_time, limit_time_utc, limit_diff; time_t limit_time, limit_time_utc, limit_diff;
struct tm *limit_tm = NULL, *limit_tm_utc = NULL; struct tm *limit_tm = NULL, *limit_tm_utc = NULL;
// Get current time // Get current time
@ -511,4 +514,121 @@ Pandora_Wmi::convertWMIDate (string wmi_date, SYSTEMTIME *system_time)
system_time->wHour = atoi (wmi_date.substr (8, 2).c_str()); system_time->wHour = atoi (wmi_date.substr (8, 2).c_str());
system_time->wMinute = atoi (wmi_date.substr (10, 2).c_str()); system_time->wMinute = atoi (wmi_date.substr (10, 2).c_str());
system_time->wSecond = atoi (wmi_date.substr (12, 2).c_str()); system_time->wSecond = atoi (wmi_date.substr (12, 2).c_str());
} }
/**
* Runs a program in a new process.
*
* @param command Command to run, with parameters
*/
bool
Pandora_Wmi::runProgram (string command) {
PROCESS_INFORMATION process_info;
STARTUPINFO startup_info;
bool success;
char *cmd;
if (command == "")
return false;
ZeroMemory (&startup_info, sizeof (startup_info));
startup_info.cb = sizeof (startup_info);
ZeroMemory (&process_info, sizeof (process_info));
pandoraDebug ("Start process \"%s\".", command.c_str ());
cmd = strdup (command.c_str ());
success = CreateProcess (NULL, cmd, NULL, NULL, FALSE, 0,
NULL, NULL, &startup_info, &process_info);
pandoraFree (cmd);
if (success) {
pandoraDebug ("The process \"%s\" was started.", command.c_str ());
return true;
}
pandoraLog ("Could not start process \"%s\". Error %d", command.c_str (),
GetLastError());
return false;
}
/**
* Start a Windows service.
*
* @param service_name Service internal name to start.
*
* @retval true If the service started.
* @retval false If the service could not start. A log message is created.
*/
bool
Pandora_Wmi::startService (string service_name) {
SC_HANDLE manager, service;
bool success;
manager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (manager == NULL) {
pandoraLog ("Could not access to service \"%s\" to start.",
service_name.c_str ());
return false;
}
service = OpenService (manager, service_name.c_str (), GENERIC_EXECUTE);
if (service == NULL) {
pandoraLog ("Could not access to service \"%s\" to start.",
service_name.c_str ());
CloseServiceHandle (manager);
return false;
}
success = StartService (service, 0, NULL);
CloseServiceHandle (service);
CloseServiceHandle (manager);
if (! success) {
pandoraLog ("Could not start service \"%s\". (Error %d)",
service_name.c_str (), GetLastError ());
}
return success;
}
/**
* Stop a Windows service.
*
* @param service_name Service internal name to stop.
*
* @retval true If the service started.
* @retval false If the service could not stop. A log message is created.
*/
bool
Pandora_Wmi::stopService (string service_name) {
SC_HANDLE manager, service;
bool success;
manager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (manager == NULL) {
pandoraLog ("Could not access to service \"%s\" to stop.",
service_name.c_str ());
return false;
}
service = OpenService (manager, service_name.c_str (), GENERIC_EXECUTE);
if (service == NULL) {
pandoraLog ("Could not access to service \"%s\" to stop.",
service_name.c_str ());
CloseServiceHandle (manager);
return false;
}
success = ControlService (service, SERVICE_CONTROL_STOP, NULL);
CloseServiceHandle (service);
CloseServiceHandle (manager);
if (! success) {
pandoraLog ("Could not stop service \"%s\". (Error %d)",
service_name.c_str (), GetLastError ());
}
return success;
}

View File

@ -46,10 +46,21 @@ namespace Pandora_Wmi {
string getOSName (); string getOSName ();
string getOSVersion (); string getOSVersion ();
string getOSBuild (); string getOSBuild ();
string getSystemName (); string getSystemName ();
void getEventList (string source, string type, string code, string pattern, int interval, list<string> &event_list);
string getTimestampLimit (int interval); void getEventList (string source,
void convertWMIDate (string wmi_date, SYSTEMTIME *system_time); string type,
string code,
string pattern,
int interval,
list<string> &event_list);
string getTimestampLimit (int interval);
void convertWMIDate (string wmi_date,
SYSTEMTIME *system_time);
bool runProgram (string command);
bool startService (string service_name);
bool stopService (string service_name);
}; };
#endif #endif

View File

@ -202,19 +202,20 @@ Windows_Service::install (LPCTSTR application_binary_path) {
} }
/* Crerate the service */ /* Crerate the service */
sc_service = CreateService (sc_manager, /* SCManager database */ sc_service = CreateService (sc_manager, /* SCManager database */
service_name, /* name of service */ service_name, /* name of service */
service_display_name, /* service name to display */ service_display_name, /* service name to display */
SERVICE_ALL_ACCESS, /* desired access */ SERVICE_ALL_ACCESS, /* desired access */
SERVICE_WIN32_OWN_PROCESS, /* service type */ SERVICE_WIN32_OWN_PROCESS |
SERVICE_AUTO_START, /* start type */ SERVICE_INTERACTIVE_PROCESS, /* service type, interactive */
SERVICE_ERROR_NORMAL, /* error control type */ SERVICE_AUTO_START, /* start type */
application_binary_path, /* service's binary */ SERVICE_ERROR_NORMAL, /* error control type */
NULL, /* no load ordering group */ application_binary_path, /* service's binary */
NULL, /* no tag identifier */ NULL, /* no load ordering group */
NULL, /* no dependencies */ NULL, /* no tag identifier */
NULL, /* LocalSystem account */ NULL, /* no dependencies */
NULL /* no password */ ); NULL, /* LocalSystem account */
NULL /* no password */ );
if (sc_service == NULL) { if (sc_service == NULL) {
DWORD err = GetLastError(); DWORD err = GetLastError();