* @copyright 2003-2015 PgPool Global Development Group
* @version CVS: $Id$
*/
require_once('common.php');
$tpl->assign('help', basename( __FILE__, '.php'));
if (!isset($_SESSION[SESSION_LOGIN_USER])) {
header('Location: login.php');
exit();
}
$configParam = array();
$error = array();
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else {
$action = FALSE;
}
/* --------------------------------------------------------------------- */
/* Set parameters' info and current vales */
/* --------------------------------------------------------------------- */
// Get parameters' info
$pgpoolConfigParamAll = $pgpoolConfigParam + $pgpoolConfigBackendParam +
$pgpoolConfigWdOtherParam + $pgpoolConfigHbDestinationParam +
$pgpoolConfigWdNodeParam + $pgpoolConfigWdHbNodeParam;
$tpl->assign('pgpoolConfigParamAll', $pgpoolConfigParamAll);
$configValue = readConfigParams();
foreach ($pgpoolConfigParam as $key => $value) {
if (!isset($configValue[$key]) ) {
$configValue[$key] = (isset($value['default'])) ?
$value['default'] : NULL;
}
}
$params = $configValue; // referenced by smarty_function_custom_tr_pgconfig()
/* --------------------------------------------------------------------- */
/* Add or Cancel */
/* --------------------------------------------------------------------- */
switch ($action) {
case 'add':
case 'add_wd':
case 'add_heartbeat_destination':
case 'add_watchdog_node':
case 'add_watchdog_heartbeat_node':
$configValue = arrangePostData();
$configValue = doAdd($configValue);
$tpl->assign('params', $configValue);
$tpl->assign('isAdd', ($action == 'add'));
$tpl->assign('isAddWd', ($action == 'add_wd'));
$tpl->assign('isAddHeartbeatDestination', ($action == 'add_heartbeat_destination'));
$tpl->assign('isAddHealthcheckPerNode', ($action == 'add_healthcheck_per_node'));
$tpl->assign('isAddWdHeartbeatNode', ($action == 'add_watchdog_heartbeat_node'));
$tpl->display('pgconfig.tpl');
return;
case 'cancel':
case 'cancel_wd':
case 'cancel_heartbeat_destination':
case 'cancel_watchdog_node':
case 'cancel_watchdog_heartbeat_node':
$configValue = arrangePostData();
$configValue = doCancel($configValue, $action);
$tpl->assign('params', $configValue);
$tpl->assign('isAdd', FALSE);
$tpl->assign('isAddWd', FALSE);
$tpl->assign('isAddHeartbeatDestination', FALSE);
$tpl->assign('isAddWdNode', FALSE);
$tpl->assign('isAddWdHeartbeatNode', FALSE);
$tpl->display('pgconfig.tpl');
return;
}
/* --------------------------------------------------------------------- */
/* Update or Delete */
/* --------------------------------------------------------------------- */
/**
* check $configFile
*/
switch ($action) {
case 'update':
$configValue = arrangePostData();
$error = doCheck();
if (! $error) {
if (is_writable(_PGPOOL2_CONFIG_FILE)) {
writeConfigFile($configValue, $pgpoolConfigParamAll);
$tpl->assign('status', 'success');
// Read all params again
$configValue = readConfigParams();
} else {
$errorCode = 'e4003';
$tpl->assign('errorCode', $errorCode);
$tpl->display('error.tpl');
exit();
}
} else {
$tpl->assign('status', 'fail');
}
break;
case 'delete':
case 'delete_wd':
case 'delete_heartbeat_destination':
case 'delete_healthcheck_per_node':
case 'delete_watchdog_node':
case 'delete_watchdog_heartbeat_node':
$num = $_POST['num'];
switch ($action) {
case 'delete':
deleteBackendHost($num, $configValue); break;
case 'delete_wd':
deleteWdOther($num, $configValue); break;
case 'delete_heartbeat_destination':
deleteHeartbeatDestination($num, $configValue); break;
case 'delete_healthcheck_per_node':
deleteHealthcheckPerNode($num, $configValue); break;
case 'delete_watchdog_node':
deleteWdNode($num, $configValue); break;
case 'delete_watchdog_heartbeat_node':
deleteWdHeartbeatNode($num, $configValue); break;
}
break;
case 'reset':
default:
}
/* Set each empty object if null */
if (! isset($configValue['backend_hostname'])) {
$configValue['backend_hostname'][0] = NULL;
$configValue['backend_port'][0] = NULL;
$configValue['backend_weight'][0] = NULL;
$configValue['backend_data_directory'][0] = NULL;
$configValue['backend_flag'][0] = NULL;
}
if (! isset($configValue['heartbeat_destination'])) {
$configValue['heartbeat_destination'][0] = NULL;
$configValue['heartbeat_destination_port'][0] = NULL;
$configValue['heartbeat_device'][0] = NULL;
}
if (! isset($configValue['other_pgpool_hostname'])) {
$configValue['other_pgpool_hostname'][0] = NULL;
$configValue['other_pgpool_port'][0] = NULL;
$configValue['other_wd_port'][0] = NULL;
}
if (! isset($configValue['health_check_period'])) {
$configValue['health_check_period0'][0] = NULL;
$configValue['other_pgpool_port'][0] = NULL;
$configValue['other_wd_port'][0] = NULL;
}
if (! isset($configValue['hostname'])) {
$configValue['hostname'][0] = NULL;
$configValue['wd_port'][0] = NULL;
$configValue['pgpool_port'][0] = NULL;
}
if (! isset($configValue['heartbeat_hostname'])) {
$configValue['heartbeat_hostname'][0] = NULL;
$configValue['heartbeat_port'][0] = NULL;
$configValue['heartbeat_device'][0] = NULL;
}
$tpl->assign('error', $error);
$tpl->assign('params', $configValue);
$params = $configValue; // referenced by smarty_function_custom_tr_pgconfig()
$tpl->display('pgconfig.tpl');
/* --------------------------------------------------------------------- */
/* Functions */
/* --------------------------------------------------------------------- */
/**
* check POST value
*
* @param string $key
* @param string $value
* @param array $configParam
* @param string $error
*/
function check($key, $define, &$configParam ,&$error)
{
if (! paramExists($key) || ! isset($configParam[$key])) { return; }
if (isset($define['parent'])) {
$ignore_ok = FALSE;
foreach ($define['parent'] as $_param => $_expected_value) {
if (! isset($configParam[$_param]) ||
$configParam[$_param] != $_expected_value)
{
$ignore_ok = TRUE;
}
if ($ignore_ok) { return; }
}
}
$is_ok = FALSE;
switch ($define['type']) {
case 'B':
$is_ok = checkBoolean($configParam[$key]);
// allow true/false and on/off as input format,
// but write with only on/off format.
if ($configParam[$key] == 'true') {
$configParam[$key] = 'on';
} elseif ($configParam[$key] == 'false') {
$configParam[$key] = 'off';
}
break;
case 'C':
$is_ok = checkString($configParam[$key], $define);
break;
case 'F':
$is_ok = checkFloat($configParam[$key], $define['min'], $define['max']);
break;
case 'N':
$is_ok = checkInteger($configParam[$key], $define['min'], $define['max']);
break;
}
if ($is_ok === FALSE) {
$error[$key] = TRUE;
}
}
/**
* check string value
*
* @param string $str
* @param string $pattern
* @return bool
*/
function checkString($str, $pattern)
{
// NULL is OK?
if (empty($str) && isset($pattern['null_ok']) && $pattern['null_ok'] == TRUE) {
return TRUE;
// regex test
} elseif (preg_match("/{$pattern['regexp']}/", $str)) {
return TRUE;
} else {
return FALSE;
}
}
/**
* check integer value
*
* @param int $str
* @param int $min
* @param int $max
* @return bool
*/
function checkInteger($str, $min, $max)
{
if (is_numeric($str)) {
$minLen = strlen($min);
$maxLen = strlen($max);
if ($str $max) {
return FALSE;
} else {
return TRUE;
}
}
return TRUE;
}
/**
* check float value
*
* @param float $str
* @param float $min
* @param float $max
* @return bool
*/
function checkFloat($str, $min, $max)
{
if (is_numeric($str)) {
if ($str $max) {
return FALSE;
}
return TRUE;
}
return TRUE;
}
/**
* Check Boolean value
*
* @param bool $str
* @return bool
*/
function checkBoolean($str)
{
if (in_array($str, array('true', 'false', 'on', 'off'))) {
return TRUE;
} else {
return FALSE;
}
}
/**
* Check if there is no paradoxes in settings
*/
function checkLogical($configValue)
{
$errors = array();
// pgpool's mode
if (!hasBackendClusteringMode()){
if ($configValue['replication_mode'] == 'on' && $configValue['master_slave_mode'] == 'on') {
$errors['replication_mode'] = TRUE;
$errors['master_slave_mode'] = TRUE;
}
}
// syslog
if ($configValue['log_destination'] && $configValue['log_destination'] == 'syslog') {
if (empty($configValue['syslog_facility'])) { $errors['syslog_facility'] = TRUE; }
if (empty($configValue['syslog_ident'])) { $errors['syslog_ident'] = TRUE; }
}
// health check
if ($configValue['health_check_period'] > 0) {
if (empty($configValue['health_check_user'])) { $errors['health_check_user'] = TRUE; }
}
// streaming replication
if (hasBackendClusteringMode()){
if ($configValue['backend_clustering_mode'] == 'streaming_replication')
{
if (empty($configValue['sr_check_user'])) { $errors['sr_check_user'] = TRUE; }
}
} else {
if ($configValue['master_slave_mode'] == 'on' &&
$configValue['master_slave_sub_mode'] == 'stream')
{
if (empty($configValue['sr_check_user'])) { $errors['sr_check_user'] = TRUE; }
}
}
// watchdog
if ($configValue['use_watchdog'] == 'on') {
if (empty($configValue['delegate_IP'])) { $errors['delegate_IP'] = TRUE; }
if (_PGPOOL2_VERSION >= 4.2) {
if (empty($configValue['hostname'])) { $errors['hostname'] = TRUE; }
} else {
if (empty($configValue['wd_hostname'])) { $errors['wd_hostname'] = TRUE; }
}
}
// memqcache
if ($configValue['memory_cache_enabled'] == 'on') {
if (empty($configValue['wd_lifecheck_query'])) {
$errors['wd_lifecheck_query'] = TRUE;
}
switch ($configValue['memqcache_method']) {
case 'shmem':
if (empty($configValue['memqcache_total_size'])) {
$errors['memqcache_total_size'] = TRUE;
}
if (empty($configValue['memqcache_max_num_cache'])) {
$errors['memqcache_max_num_cache'] = TRUE;
}
if (empty($configValue['memqcache_cache_block_size'])) {
$errors['memqcache_cache_block_size'] = TRUE;
}
break;
case 'memcached':
if (empty($configValue['memqcache_memcached_host'])) {
$errors['memqcache_memcached_host'] = TRUE;
}
if (empty($configValue['memqcache_memcached_port'])) {
$errors['memqcache_memcached_port'] = TRUE;
}
break;
}
}
return $errors;
}
/* --------------------------------------------------------------------- */
/**
* Write pgpool.conf
*
* @param array $configValue
* @param array $pgpoolConfigParam
*/
function writeConfigFile($configValue, $pgpoolConfigParamAll)
{
$configFile = array();
$originalConfigFile = @file(_PGPOOL2_CONFIG_FILE);
foreach ($originalConfigFile as $line) {
// Not-empty lines
if (preg_match("/^\w/", $line)) {
list($key, $value) = explode("=", $line);
$key = trim($key);
$key_wo_num = preg_replace('/\d*$/', '', $key);
// Modify the parameter' value if posted.
// (Ignore the params like "backend_hostname_0" and "health_check_*" which will be arranged in below)
if (! isset($pgpoolConfigParamAll[$key_wo_num]['multiple']) &&
! isset($pgpoolConfigParamAll[$key_wo_num]['healthcheck'])) {
if (isset($configValue[$key_wo_num])) {
$value = $configValue[$key_wo_num];
if (strcmp($pgpoolConfigParamAll[$key_wo_num]['type'], "C") == 0) {
$value = "'{$value}'";
}
$configFile[] = "{$key_wo_num} = {$value}\n";
} else {
$configFile[] = $line;
}
}
// comment or empty lines
} else {
$configFile[] = $line;
}
}
/*
* global health check parameters
*/
$health_check_params = getPerNodeHealthCheckParams();
if (isset($configValue['health_check_period'])) {
foreach ($health_check_params as $key) {
$value = (isset($configValue[$key])) ? $configValue[$key] : NULL;
if (strcmp($pgpoolConfigParamAll[$key]['type'], "C") == 0) {
$value = "'{$value}'";
}
$configFile[] = "{$key} = {$value}\n";
}
}
/*
* per node health check parameters
*/
$i = 0;
foreach ($configValue as $k => $v) {
if (preg_match("/^health_check_period\d+$/", $k)) {
$num = preg_replace("/[^0-9]/", '', $k);
foreach ($health_check_params as $key) {
$value = (isset($configValue[$key . $num])) ? $configValue[$key . $num] : NULL;
if (strcmp($pgpoolConfigParamAll[$key]['type'], "C") == 0) {
$value = "'{$value}'";
}
$configFile[] = "{$key}{$num} = {$value}\n";
}
}
}
/*
* multiple parameters
*/
$param_names = getMultiParams();
foreach ($param_names as $group => $key_arr) {
if (! isset($configValue[$key_arr[0]])) {
continue;
}
for ($i = 0; $i $value) {
if (isset($_POST[$key])) {
$configValue[$key] = trim($_POST[$key]);
}
}
return $configValue;
}
/**
* Add action
*/
function doAdd($configValue)
{
global $_POST;
// Backend settings
if (isset($_POST['backend_hostname'])) {
$configValue['backend_hostname'] = $_POST['backend_hostname'];
} else {
$configValue['backend_hostname'][0] = NULL;
}
if (isset($_POST['backend_port'])) {
$configValue['backend_port'] = $_POST['backend_port'];
} else {
$configValue['backend_port'][0] = NULL;
}
if (isset($_POST['backend_weight'])) {
$configValue['backend_weight'] = $_POST['backend_weight'];
} else {
$configValue['backend_weight'][0] = NULL;
}
if (isset($_POST['backend_data_directory'])) {
$configValue['backend_data_directory'] = $_POST['backend_data_directory'];
} else {
$configValue['backend_data_directory'][0] = NULL;
}
if (paramExists('backend_flag')) {
if (isset($_POST['backend_flag'])) {
$configValue['backend_flag'] = $_POST['backend_flag'];
} else {
$configValue['backend_flag'][0] = NULL;
}
}
// watchdog's heartbeat destination settings
if(paramExists('heartbeat_hostname')){
if (isset($_POST['heartbeat_hostname'])) {
$configValue['heartbeat_hostname'] = $_POST['heartbeat_hostname'];
} else {
$configValue['heartbeat_hostname'][0] = NULL;
}
}
if(paramExists('heartbeat_port')){
if (isset($_POST['heartbeat_port'])) {
$configValue['heartbeat_port'] = $_POST['heartbeat_port'];
} else {
$configValue['heartbeat_port'][0] = NULL;
}
}
if (isset($_POST['heartbeat_device'])) {
$configValue['heartbeat_device'] = $_POST['heartbeat_device'];
} else {
$configValue['heartbeat_device'][0] = NULL;
}
if (isset($_POST['heartbeat_destination_port'])) {
$configValue['heartbeat_destination_port'] = $_POST['heartbeat_destination_port'];
} else {
$configValue['heartbeat_destination_port'][0] = NULL;
}
if (isset($_POST['heartbeat_destination'])) {
$configValue['heartbeat_destination'] = $_POST['heartbeat_destination'];
} else {
$configValue['heartbeat_destination'][0] = NULL;
}
// watchdog's other pgpool settings
if (isset($_POST['other_pgpool_hostname'])) {
$configValue['other_pgpool_hostname'] = $_POST['other_pgpool_hostname'];
} else {
$configValue['other_pgpool_hostname'][0] = NULL;
}
if (isset($_POST['other_pgpool_port'])) {
$configValue['other_pgpool_port'] = $_POST['other_pgpool_port'];
} else {
$configValue['other_pgpool_port'][0] = NULL;
}
if (isset($_POST['other_wd_port'])) {
$configValue['other_wd_port'] = $_POST['other_wd_port'];
} else {
$configValue['other_wd_port'][0] = NULL;
}
// watchdog's nodes settings
if (isset($_POST['hostname'])) {
$configValue['hostname'] = $_POST['hostname'];
} else {
$configValue['hostname'][0] = NULL;
}
if (isset($_POST['wd_port'])) {
$configValue['wd_port'] = $_POST['wd_port'];
} else {
$configValue['wd_port'][0] = NULL;
}
if (isset($_POST['pgpool_port'])) {
$configValue['pgpool_port'] = $_POST['pgpool_port'];
} else {
$configValue['pgpool_port'][0] = NULL;
}
return $configValue;
}
/**
* Cancel action
*/
function doCancel($configValue, $action)
{
global $_POST;
// Backend settings
if (isset($_POST['backend_hostname'])) {
$configValue['backend_hostname'] = $_POST['backend_hostname'];
}
if (isset($_POST['backend_port'])) {
$configValue['backend_port'] = $_POST['backend_port'];
}
if (isset($_POST['backend_weight'])) {
$configValue['backend_weight'] = $_POST['backend_weight'];
}
if (isset($_POST['backend_data_directory'])) {
$configValue['backend_data_directory'] = $_POST['backend_data_directory'];
}
if (paramExists('backend_flag') && isset($_POST['backend_flag'])) {
$configValue['backend_flag'] = $_POST['backend_flag'];
}
if ($action == 'cancel') {
array_pop($configValue['backend_hostname']);
array_pop($configValue['backend_port']);
array_pop($configValue['backend_weight']);
array_pop($configValue['backend_data_directory']);
array_pop($configValue['backend_flag']);
}
// watchdog's device settings
if (isset($_POST['heartbeat_device'])) {
$configValue['heartbeat_device'] = $_POST['heartbeat_device'];
}
if (isset($_POST['heartbeat_destination'])) {
$configValue['heartbeat_destination'] = $_POST['heartbeat_destination'];
}
if (isset($_POST['heartbeat_destination_port'])) {
$configValue['heartbeat_destination_port'] = $_POST['heartbeat_destination_port'];
}
if (isset($_POST['heartbeat_hostname'])) {
$configValue['heartbeat_hostname'] = $_POST['heartbeat_hostname'];
}
if (isset($_POST['heartbeat_port'])) {
$configValue['heartbeat_port'] = $_POST['heartbeat_port'];
}
if ($action == 'cancel_heartbeat_destination') {
array_pop($configValue['heartbeat_destination']);
array_pop($configValue['heartbeat_destination_port']);
array_pop($configValue['heartbeat_device']);
}
if ($action == 'cancel_watchdog_heartbeat_node') {
array_pop($configValue['heartbeat_hostname']);
array_pop($configValue['heartbeat_port']);
array_pop($configValue['heartbeat_device']);
}
// watchdog's other pgpool settings
if (isset($_POST['other_pgpool_hostname'])) {
$configValue['other_pgpool_hostname'] = $_POST['other_pgpool_hostname'];
}
if (isset($_POST['other_pgpool_port'])) {
$configValue['other_pgpool_port'] = $_POST['other_pgpool_port'];
}
if (isset($_POST['other_wd_port'])) {
$configValue['other_wd_port'] = $_POST['other_wd_port'];
}
if ($action == 'cancel_wd') {
array_pop($configValue['other_pgpool_hostname']);
array_pop($configValue['other_pgpool_port']);
array_pop($configValue['other_wd_port']);
}
// watchdog nodes settings
if (isset($_POST['hostname'])) {
$configValue['hostname'] = $_POST['hostname'];
}
if (isset($_POST['wd_port'])) {
$configValue['wd_port'] = $_POST['wd_port'];
}
if (isset($_POST['pgpool_port'])) {
$configValue['pgpool_port'] = $_POST['pgpool_port'];
}
if ($action == 'cancel_watchdog_node') {
array_pop($configValue['hostname']);
array_pop($configValue['wd_port']);
array_pop($configValue['pgpool_port']);
}
return $configValue;
}
/**
* Check all params
*/
function doCheck()
{
global $pgpoolConfigParam;
global $configValue;
global $pgpoolConfigBackendParam;
global $pgpoolConfigHbDestinationParam;
global $pgpoolConfigWdOtherParam;
global $pgpoolConfigHealthCheckParam;
global $pgpoolConfigWdNodeParam;
global $pgpoolConfigWdHbNodeParam;
global $_POST;
$error = array();
/*
* Confirmations of value except backend host
*/
foreach ($pgpoolConfigParam as $key => $value) {
check($key, $value, $configValue, $error);
}
/*
* Delete empty backend node
*/
foreach ($_POST['backend_hostname'] as $no => $str) {
if ($str == '') {
foreach ($pgpoolConfigBackendParam as $key => $value) {
unset($_POST[$key][$no]);
}
}
}
/*
* copy backend value from POST data to $configValue
*/
foreach ($pgpoolConfigBackendParam as $key => $value) {
if (isset($_POST[$key]) && $_POST[$key] != '') {
/*
* set per node health check params
*/
if ($key == 'backend_hostname') {
foreach ($_POST[$key] as $no => $str) {
if (isset($_POST['health_check_period' . $no]) &&
$_POST['health_check_period' . $no] != '') {
$health_check_params = getPerNodeHealthCheckParams();
foreach ($health_check_params as $param) {
$configValue[$param . $no] = trim($_POST[$param . $no]);
}
}
}
}
$configValue[$key] = $_POST[$key];
}
}
/*
* check backend value
*/
if (isset($configValue['backend_hostname'])) {
for ($i = 0; $i $value) {
if (isset($_POST[$key])) {
$configValue[$key] = $_POST[$key];
}
}
if (isset($configValue['heartbeat_destination'])) {
for ($i = 0; $i $value) {
if (isset($_POST[$key])) {
$configValue[$key] = $_POST[$key];
}
}
if (isset($configValue['other_pgpool_hostname'])) {
for ($i = 0; $i $value) {
if (isset($_POST[$key])) {
$configValue[$key] = $_POST[$key];
}
}
if (isset($configValue['heartbeat_hostname'])) {
for ($i = 0; $i $value) {
if (isset($_POST[$key])) {
$configValue[$key] = $_POST[$key];
}
}
if (isset($configValue['hostname'])) {
for ($i = 0; $i