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>
* windows/pandora_wmi.cc,

View File

@ -101,9 +101,8 @@ namespace Pandora_Modules {
* The module does not satisfy its interval.
*/
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.
*/

View File

@ -35,26 +35,28 @@ using namespace Pandora;
using namespace Pandora_Modules;
using namespace Pandora_Strutils;
#define TOKEN_NAME ("module_name ")
#define TOKEN_TYPE ("module_type ")
#define TOKEN_INTERVAL ("module_interval ")
#define TOKEN_EXEC ("module_exec ")
#define TOKEN_PROC ("module_proc ")
#define TOKEN_SERVICE ("module_service ")
#define TOKEN_FREEDISK ("module_freedisk ")
#define TOKEN_FREEMEMORY ("module_freememory")
#define TOKEN_CPUUSAGE ("module_cpuusage ")
#define TOKEN_ODBC ("module_odbc ")
#define TOKEN_MAX ("module_max ")
#define TOKEN_MIN ("module_min ")
#define TOKEN_DESCRIPTION ("module_description ")
#define TOKEN_ODBC_QUERY ("module_odbc_query ")
#define TOKEN_LOGEVENT ("module_logevent")
#define TOKEN_SOURCE ("module_source ")
#define TOKEN_EVENTTYPE ("module_eventtype ")
#define TOKEN_EVENTCODE ("module_eventcode ")
#define TOKEN_PATTERN ("module_pattern ")
#define TOKEN_ASYNC ("module_async")
#define TOKEN_NAME ("module_name ")
#define TOKEN_TYPE ("module_type ")
#define TOKEN_INTERVAL ("module_interval ")
#define TOKEN_EXEC ("module_exec ")
#define TOKEN_PROC ("module_proc ")
#define TOKEN_SERVICE ("module_service ")
#define TOKEN_FREEDISK ("module_freedisk ")
#define TOKEN_FREEMEMORY ("module_freememory")
#define TOKEN_CPUUSAGE ("module_cpuusage ")
#define TOKEN_ODBC ("module_odbc ")
#define TOKEN_MAX ("module_max ")
#define TOKEN_MIN ("module_min ")
#define TOKEN_DESCRIPTION ("module_description ")
#define TOKEN_ODBC_QUERY ("module_odbc_query ")
#define TOKEN_LOGEVENT ("module_logevent")
#define TOKEN_SOURCE ("module_source ")
#define TOKEN_EVENTTYPE ("module_eventtype ")
#define TOKEN_EVENTCODE ("module_eventcode ")
#define TOKEN_PATTERN ("module_pattern ")
#define TOKEN_ASYNC ("module_async")
#define TOKEN_WATCHDOG ("module_watchdog ")
#define TOKEN_START_COMMAND ("module_start_command ")
string
parseLine (string line, string token) {
@ -90,28 +92,32 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
string module_freedisk, module_cpuusage, module_odbc;
string module_odbc_query, module_dsn, module_freememory;
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;
bool numeric;
Module_Type type;
module_name = "";
module_type = "";
module_min = "";
module_max = "";
module_description = "";
module_interval = "";
module_exec = "";
module_proc = "";
module_service = "";
module_odbc = "";
module_odbc_query = "";
module_odbc = "";
module_logevent = "";
module_source = "";
module_eventtype = "";
module_name = "";
module_type = "";
module_min = "";
module_max = "";
module_description = "";
module_interval = "";
module_exec = "";
module_proc = "";
module_service = "";
module_odbc = "";
module_odbc_query = "";
module_odbc = "";
module_logevent = "";
module_source = "";
module_eventtype = "";
module_eventcode = "";
module_pattern = "";
module_pattern = "";
module_async = "";
module_watchdog = "";
module_start_command = "";
stringtok (tokens, definition, "\n");
@ -182,6 +188,12 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
if (module_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++;
}
@ -192,10 +204,36 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
module_exec);
} else if (module_proc != "") {
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 != "") {
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 != "") {
module = new Pandora_Module_Freedisk (module_name,
module_freedisk);
@ -221,10 +259,10 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
module_odbc_query);
} else if (module_logevent != "") {
module = new Pandora_Module_Logevent (module_name,
module_source,
module_eventtype,
module_eventcode,
module_pattern);
module_source,
module_eventtype,
module_eventcode,
module_pattern);
} else {
return NULL;
}
@ -296,6 +334,7 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
module_interval.c_str (),
module_name.c_str ());
}
}
}
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 (),
this->process_name.begin (), (int (*) (int)) tolower);
this->setKind (module_proc_str);
this->setKind (module_proc_str);
this->watchdog = false;
this->start_command = "";
}
string
@ -53,6 +56,26 @@ Pandora_Module_Proc::getProcessName () const {
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
async_run (Pandora_Module_Proc *module) {
HANDLE *processes = NULL;
@ -72,6 +95,9 @@ async_run (Pandora_Module_Proc *module) {
while (1) {
processes = getProcessHandles (module->getProcessName ());
if (processes == NULL) {
if (module->isWatchdog ()) {
Pandora_Wmi::runProgram (module->getStartCommand ());
}
Sleep (2000);
continue;
}
@ -106,6 +132,10 @@ async_run (Pandora_Module_Proc *module) {
Pandora_Windows_Service::getInstance ()->sendXml (modules);
}
if (res == 0 && module->isWatchdog ()) {
Pandora_Wmi::runProgram (module->getStartCommand ());
}
/* Free handles */
for (i = 0; i < nprocess; i++)
CloseHandle (processes[i]);

View File

@ -30,13 +30,20 @@ namespace Pandora_Modules {
class Pandora_Module_Proc : public Pandora_Module {
private:
string process_name;
HANDLE thread;
HANDLE thread;
bool watchdog;
string start_command;
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->setKind (module_service_str);
this->thread = 0;
this->thread = 0;
this->watchdog = false;
}
string
@ -54,6 +55,17 @@ Pandora_Module_Service::getServiceName () const {
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)
void
@ -107,8 +119,8 @@ async_run (Pandora_Module_Service *module) {
continue;
event_id = record->EventID & 0x0000ffff;
/* Those numbers are the code for service start/stopping */
if (event_id == 7035 || event_id == 7036) {
/* This number is the code for service start/stopping */
if (event_id == 7036) {
service_event = true;
break;
}
@ -123,6 +135,10 @@ async_run (Pandora_Module_Service *module) {
prev_res = str_res;
Pandora_Windows_Service::getInstance ()->sendXml (modules);
}
if (res == 0 && module->isWatchdog ()) {
Pandora_Wmi::startService (module->getServiceName ());
}
}
CloseHandle (event);
CloseEventLog (event_log);

View File

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

View File

@ -272,3 +272,22 @@ string
Pandora::getPandoraAgentVersion () {
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 pandoraLog (char *format, ...);
void pandoraFree (void * e);
bool is_enabled (string value);
/**
* Super-class exception.
*

View File

@ -37,8 +37,6 @@ using namespace std;
using namespace Pandora;
using namespace Pandora_Modules;
using namespace Pandora_Strutils;
string enabled_values[] = {"enabled", "1", "on", "yes", "si", "", "ok", ""};
Pandora_Windows_Service::Pandora_Windows_Service ()
: Windows_Service (NULL, NULL, NULL) {
@ -101,23 +99,6 @@ Pandora_Windows_Service::getInstance () {
void
Pandora_Windows_Service::start () {
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

View File

@ -25,17 +25,18 @@
#include <algorithm>
#include <cctype>
#include <sstream>
#include <ctime>
#include <ctime>
#include <winuser.h>
using namespace std;
using namespace Pandora_Wmi;
static LPWSTR
getWmiStr (LPCWSTR computer) {
static WCHAR wmi_str [256];
wcscpy (wmi_str, L"winmgmts:{impersonationLevel=impersonate}!\\\\");
static WCHAR wmi_str[256];
wcscpy (wmi_str, L"winmgmts:\\\\");
if (computer) {
wcsncat (wmi_str, computer, 128);
} else {
@ -43,7 +44,7 @@ getWmiStr (LPCWSTR computer) {
}
wcscat (wmi_str, L"\\root\\cimv2");
return wmi_str;
}
@ -388,7 +389,9 @@ Pandora_Wmi::getSystemName () {
* @return The list of events.
*/
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;
CDispPtr wmi_svc, quickfixes;
char *value = NULL;
@ -453,8 +456,8 @@ Pandora_Wmi::getEventList (string source, string type, string code, string patte
*/
string
Pandora_Wmi::getTimestampLimit (int interval) {
char limit_str[26], diff_sign;
time_t limit_time, limit_time_utc, limit_diff;
char limit_str[26], diff_sign;
time_t limit_time, limit_time_utc, limit_diff;
struct tm *limit_tm = NULL, *limit_tm_utc = NULL;
// 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->wMinute = atoi (wmi_date.substr (10, 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 getOSVersion ();
string getOSBuild ();
string getSystemName ();
void getEventList (string source, string type, string code, string pattern, int interval, list<string> &event_list);
string getTimestampLimit (int interval);
void convertWMIDate (string wmi_date, SYSTEMTIME *system_time);
string getSystemName ();
void getEventList (string source,
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

View File

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