<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 encoding=utf-8: */
// +----------------------------------------------------------------------+
// | Eventum - Issue Tracking System |
// +----------------------------------------------------------------------+
// | Copyright (c) 2003 - 2008 MySQL AB |
// | Copyright (c) 2008 - 2009 Sun Microsystem Inc. |
// | |
// | 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 of the License, 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: |
// | |
// | Free Software Foundation, Inc. |
// | 59 Temple Place - Suite 330 |
// | Boston, MA 02111-1307, USA. |
// +----------------------------------------------------------------------+
// | Authors: João Prado Maia <hide@address.com> |
// +----------------------------------------------------------------------+
//
// @(#) $Id: class.monitor.php 3797 2009-01-12 20:14:39Z balsdorf $
//
require_once("DB.php");
require_once(APP_INC_PATH . "class.misc.php");
class Monitor
{
/**
* Checks the mail queue logs for any email that wasn't delivered.
*
* @access public
*/
function checkMailQueue()
{
// try to connect to the database
$dsn = array(
'phptype' => APP_SQL_DBTYPE,
'hostspec' => APP_SQL_DBHOST,
'database' => APP_SQL_DBNAME,
'username' => APP_SQL_DBUSER,
'password' => APP_SQL_DBPASS
);
$dbh = DB::connect($dsn);
$limit = 10;
$stmt = "SELECT
maq_id,
COUNT(mql_id) total_tries
FROM
" . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "mail_queue,
" . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "mail_queue_log
WHERE
maq_status='error' AND
maq_id=mql_maq_id
GROUP BY
maq_id";
$queue_ids = $dbh->getCol($stmt);
if (count($queue_ids) > 0) {
echo "ERROR: There is a total of " . count($queue_ids) . " queued emails that were not sent yet.\n";
}
}
/**
* Checks the free disk space status on the server.
*
* @access public
*/
function checkDiskspace($partition)
{
$low_limit = 5;
$high_limit = 15;
$total_space = disk_total_space($partition);
$free_space = disk_free_space($partition);
$free_percentage = ($free_space * 100) / $total_space;
if ($free_percentage < $low_limit) {
echo ev_gettext("ERROR: Almost no free disk space left (percentage left") . ": $free_percentage)\n";
exit;
}
if ($free_percentage < $high_limit) {
echo ev_gettext("ERROR: Free disk space left is getting very low (percentage left") . ": $free_percentage)\n";
}
}
/**
* Checks on the status of the required configuration and auxiliary files
* and directories.
*
* @access public
* @param array $required_files An array of files that should be checked on.
*/
function checkConfiguration($required_files)
{
foreach ($required_files as $file_path => $options) {
// check if file exists
if (!file_exists($file_path)) {
echo ev_gettext("ERROR: File could not be found (path") . ": $file_path)\n";
continue;
}
// check the owner and group for these files
list($owner, $group) = Monitor::_getOwnerAndGroup($file_path);
if ((@$options['check_owner']) && ($options['owner'] != $owner)) {
echo ev_gettext('ERROR: File owner mismatch (path: %1$s; current owner: %2$s; correct owner: %3$s)', $file_path, $owner, $options['owner']) . "\n";
}
if ((@$options['check_group']) && ($options['group'] != $group)) {
echo ev_gettext('ERROR: File group mismatch (path: %1$s; current group: %2$s; correct group: %3$s)', $file_path, $group, $options['group']) . "\n";
}
// check permission bits
$perm = Monitor::_getOctalPerms($file_path);
if ((@$options['check_permission']) && ($options['permission'] != $perm)) {
echo ev_gettext('ERROR: File permission mismatch (path: %1$s; current perm: %2$s; correct perm: %3$s)', $file_path, $perm, $options['permission']) . "\n";
}
// check filesize
if ((@$options['check_filesize']) && (filesize($file_path) < $options['filesize'])) {
echo ev_gettext('ERROR: File size mismatch (path: %1$s; current filesize: %2$s)', $file_path, filesize($file_path)) . ")\n";
}
}
$required_directories = array(
APP_PATH . 'misc/routed_emails' => array(
'check_permission' => true,
'permission' => 770,
),
APP_PATH . 'misc/routed_notes' => array(
'check_permission' => true,
'permission' => 770,
),
APP_PATH . 'setup' => array(
'check_permission' => true,
'permission' => 100,
),
);
foreach ($required_directories as $dir_path => $options) {
// check if directory exists
if (!file_exists($dir_path)) {
echo ev_gettext('ERROR: Directory could not be found (path: %1$s)', $dir_path) . "\n";
continue;
}
// check permission bits
$perm = Monitor::_getOctalPerms($dir_path);
if ((@$options['check_permission']) && ($options['permission'] != $perm)) {
echo ev_gettext('ERROR: Directory permission mismatch (path: %1$s; current perm: %2$s; correct perm: %3$s)', $dir_path, $perm, $options['permission']) . "\n";
}
}
}
/**
* Checks on the status of the MySQL database.
*
* @access public
*/
function checkDatabase()
{
// try to connect to the database
$dsn = array(
'phptype' => APP_SQL_DBTYPE,
'hostspec' => APP_SQL_DBHOST,
'database' => APP_SQL_DBNAME,
'username' => APP_SQL_DBUSER,
'password' => APP_SQL_DBPASS
);
$dbh = DB::connect($dsn);
if (PEAR::isError($dbh)) {
echo ev_gettext("ERROR: Could not connect to the mysql database. Detailed error message:") . "\n\n";
echo $dbh->getMessage() . '/' . $dbh->getDebugInfo();
} else {
$required_tables = array(
"custom_field",
"custom_field_option",
"custom_filter",
"customer_account_manager",
"customer_note",
"email_account",
"email_draft",
"email_draft_recipient",
"email_response",
"faq",
"faq_support_level",
"group",
"history_type",
"irc_notice",
"issue",
"issue_association",
"issue_attachment",
"issue_attachment_file",
"issue_checkin",
"issue_custom_field",
"issue_history",
"issue_quarantine",
"issue_requirement",
"issue_user",
"issue_user_replier",
"mail_queue",
"mail_queue_log",
"news",
"note",
"phone_support",
"project",
"project_category",
"project_custom_field",
"project_email_response",
"project_group",
"project_news",
"project_phone_category",
"project_priority",
"project_release",
"project_round_robin",
"project_status",
"project_status_date",
"project_user",
"reminder_action",
"reminder_action_list",
"reminder_action_type",
"reminder_field",
"reminder_history",
"reminder_level",
"reminder_level_condition",
"reminder_operator",
"reminder_priority",
"reminder_requirement",
"reminder_triggered_action",
"resolution",
"round_robin_user",
"search_profile",
"status",
"subscription",
"subscription_type",
"support_email",
"support_email_body",
"time_tracking",
"time_tracking_category",
"user"
);
// add the table prefix to all of the required tables
$required_tables = Misc::array_map_deep($required_tables, array('Monitor', '_add_table_prefix'));
// check if all of the required tables are really there
$stmt = "SHOW TABLES";
$table_list = $dbh->getCol($stmt);
for ($i = 0; $i < count($required_tables); $i++) {
if (!in_array($required_tables[$i], $table_list)) {
echo "ERROR: Could not find required table '" . $required_tables[$i] . "'\n";
}
}
}
}
/**
* Checks on the status of the IRC bot.
*
* @access public
*/
function checkIRCBot()
{
// check if any bot.php process is still running (lame, but oh well)
ob_start();
passthru("ps -ef | grep '[-]q bot.php'");
$contents = ob_get_contents();
ob_end_clean();
$lines = explode("\n", $contents);
if (count($lines) <= 1) {
echo ev_gettext("ERROR: Could not find IRC bot pid from process list.") . "\n";
}
}
/**
* Method used by the code that checks if the required tables
* do exist in the appropriate database. It returns the given
* table name prepended with the appropriate table prefix.
*
* @access private
* @param string $table_name The table name
* @return string The table name with the prefix added to it
*/
function _add_table_prefix($table_name)
{
return APP_TABLE_PREFIX . $table_name;
}
/**
* Returns the owner and group name for the given file.
*
* @access private
* @param string $file The full path to the file
* @return array The owner and group name associated with that file
*/
function _getOwnerAndGroup($file)
{
$owner_info = posix_getpwuid(fileowner($file));
$group_info = posix_getgrgid(filegroup($file));
return array(
$owner_info['name'],
$group_info['name']
);
}
/**
* Returns the octal permission string for a given file.
*
* @access private
* @param string $file The full path to the file
* @return string The octal permission string
*/
function _getOctalPerms($file)
{
return substr(sprintf("%o", fileperms($file)), -3);
}
}