From 8cae7be74890bcc2d1e3d797ae7a8e8c20591d22 Mon Sep 17 00:00:00 2001 From: PiBa-NL Date: Sun, 7 Apr 2013 00:54:56 +0200 Subject: haproxy-devel, add options for checking server health -fix adding a new server -show advanced options icon in serverpool overview --- config/haproxy-devel/haproxy.inc | 102 +++++++++++++--- config/haproxy-devel/haproxy_listeners_edit.php | 16 --- config/haproxy-devel/haproxy_pool_edit.php | 132 +++++++++++++++++---- config/haproxy-devel/haproxy_pools.php | 149 +++++++++++++----------- 4 files changed, 276 insertions(+), 123 deletions(-) diff --git a/config/haproxy-devel/haproxy.inc b/config/haproxy-devel/haproxy.inc index f949bf98..9a291f7a 100644 --- a/config/haproxy-devel/haproxy.inc +++ b/config/haproxy-devel/haproxy.inc @@ -65,6 +65,39 @@ if ($haproxy_sni_ssloffloading) { 'mode' => 'https', 'syntax' => 'req_ssl_sni -i', 'advancedoptions' => "tcp-request inspect-delay 5s\n\ttcp-request content accept if { req_ssl_hello_type 1 }"); } +$a_checktypes['none'] = array('name' => 'none', 'syntax' => '', + 'descr' => 'No health checks will be performed.'); +$a_checktypes['Basic'] = array('name' => 'Basic', 'syntax' => '', + 'descr' => 'Basic socket connection check'); +$a_checktypes['HTTP'] = array('name' => 'HTTP', 'syntax' => 'httpchk', + 'descr' => 'HTTP protocol to check on the servers health, can also be used for HTTPS servers(requirs checking the SSL box for the servers).', 'parameters' => "uri,method,version"); +/* seams this was added in HAProxy1.5dev18, haproxy-devel package is currently using 1.5dev17 +$a_checktypes['Agent'] = array('name' => 'Agent', 'syntax' => 'lb-agent-chk', 'usedifferenport' => 'yes', + 'descr' => 'Use a TCP connection to read an ASCII string of the form 100%,75%,drain,down (others in haproxy manual)'); +*/ +$a_checktypes['LDAP'] = array('name' => 'LDAP', 'syntax' => 'ldap-check', + 'descr' => 'Use LDAPv3 health checks for server testing'); +$a_checktypes['MySQL'] = array('name' => 'MySQL', 'syntax' => 'mysql-check', + 'descr' => 'Use MySQL health checks for server testing', 'parameters' => 'username'); +$a_checktypes['PostgreSQL'] = array('name' => 'PostgreSQL', 'syntax' => 'pgsql-check', + 'descr' => 'Use PostgreSQL health checks for server testing', 'parameters' => 'username'); +$a_checktypes['Redis'] = array('name' => 'Redis', 'syntax' => 'redis-check', + 'descr' => 'Test that the server correctly talks REDIS protocol.'); +$a_checktypes['SMTP'] = array('name' => 'SMTP', 'syntax' => 'smtpchk HELO', + 'descr' => 'Use SMTP HELO health checks for server testing', 'parameters' => 'domain'); +$a_checktypes['ESMTP'] = array('name' => 'ESMTP', 'syntax' => 'smtpchk EHLO', + 'descr' => 'Use ESMTP EHLO health checks for server testing', 'parameters' => 'domain'); +$a_checktypes['SSL'] = array('name' => 'SSL', 'syntax' => 'ssl-hello-chk', + 'descr' => 'Use SSLv3 client hello health checks for server testing.'); + +$a_httpcheck_method['OPTIONS'] = array('name' => 'OPTIONS', 'syntax' => 'OPTIONS'); +$a_httpcheck_method['HEAD'] = array('name' => 'HEAD', 'syntax' => 'HEAD'); +$a_httpcheck_method['GET'] = array('name' => 'GET', 'syntax' => 'GET'); +$a_httpcheck_method['POST'] = array('name' => 'POST', 'syntax' => 'POST'); +$a_httpcheck_method['PUT'] = array('name' => 'PUT', 'syntax' => 'PUT'); +$a_httpcheck_method['DELETE'] = array('name' => 'DELETE', 'syntax' => 'DELETE'); +$a_httpcheck_method['TRACE'] = array('name' => 'TRACE', 'syntax' => 'TRACE'); + function haproxy_custom_php_deinstall_command() { exec("cd /var/db/pkg && pkg_delete `ls | grep haproxy`"); exec("rm /usr/local/pkg/haproxy.inc"); @@ -323,6 +356,7 @@ function haproxy_find_acl($name) { function write_backend($fd, $name, $pool, $frontend) { if(!is_array($pool['ha_servers']['item']) && !$pool['stats_enabled']=='yes') return; + global $a_checktypes; $a_servers = &$pool['ha_servers']['item']; @@ -344,17 +378,31 @@ function write_backend($fd, $name, $pool, $frontend) { // https is an alias for tcp for clarity purpouses if(strtolower($frontend['type']) == "https") { $backend_type = "tcp"; - $httpchk = "ssl-hello-chk"; } else { $backend_type = $frontend['type']; - if(strtolower($frontend['type']) == "http") - $httpchk = "httpchk"; - else - unset($httpchk); } fwrite ($fd, "\tmode\t\t\t" . $backend_type . "\n"); - + + $check_type = $pool['check_type']; + if ($check_type != 'none') + { + $optioncheck = $a_checktypes[$check_type]['syntax']; + if ($check_type == "MySQL" || $check_type == "PostgreSQL") + $optioncheck .= " user " . $pool['monitor_username']; + if ($check_type == "SMTP" || $check_type == "ESMTP") + $optioncheck .= " " . $pool['monitor_domain']; + if ($check_type == "HTTP") + { + $uri = $pool['monitor_uri']; + if (!$uri) + $uri = "/"; + $optioncheck .= " {$pool['httpcheck_method']} {$uri} {$pool['monitor_httpversion']}"; + } + } else { + $optioncheck = "httpchk"; + } + if($pool['balance']) fwrite ($fd, "\tbalance\t\t\t" . $pool['balance'] . "\n"); @@ -397,8 +445,8 @@ function write_backend($fd, $name, $pool, $frontend) { else $uri = "/"; - if ($httpchk) - fwrite ($fd, "\toption\t\t\t{$httpchk} HEAD " . $uri . " HTTP/1.0\n"); + if ($optioncheck) + fwrite ($fd, "\toption\t\t\t{$optioncheck}\n"); if ($pool['advanced_backend']) { $adv_be = explode("\n", base64_decode($pool['advanced_backend'])); @@ -410,7 +458,7 @@ function write_backend($fd, $name, $pool, $frontend) { } } - if($pool['cookie'] && strtolower($frontend['type']) == "http") + if($pool['cookie'] && strtolower($frontend['type']) == "http") $cookie = " cookie {$pool['cookie']} "; else $cookie = ""; @@ -420,12 +468,14 @@ function write_backend($fd, $name, $pool, $frontend) { } else { $advanced_txt = ""; } - if($pool['checkinter']) - $checkinter = "check inter {$pool['checkinter']}"; - else if (strtolower($frontend['type']) != "tcp") - $checkinter = "check inter 1000"; - else - $checkinter = ""; + + if ($check_type != 'none') + { + if($pool['checkinter']) + $checkinter = "check inter {$pool['checkinter']}"; + else + $checkinter = "check inter 1000"; + } if (is_array($a_servers)) { @@ -440,7 +490,11 @@ function write_backend($fd, $name, $pool, $frontend) { } else { $isbackup = ""; } - $ssl = ($backend_type == "http" && $be['ssl'] == 'yes') ? ' ssl' : ""; + $ssl = ""; + if ($be['ssl'] == 'yes') + { + $ssl = $backend_type == "http" ? ' ssl' : ' check-ssl'; + } fwrite ($fd, "\tserver\t\t\t" . $be['name'] . " " . $be['address'].":" . $be['port'] . "$ssl $cookie $checkinter $isbackup weight " . $be['weight'] . "{$advanced_txt} {$be['advanced']}\n"); } } @@ -1047,4 +1101,20 @@ function haproxy_escapestring($configurationsting) { return str_replace('#', '\\#', $result); } +function echo_html_select($name, $keyvaluelist, $selected, $listEmptyMessage="", $onchangeEvent="") +{ + if (count($keyvaluelist)>0){ + if ($onchangeEvent != "") + $onchangeEvent .= " onchange=$onchangeEvent"; + echo ""; + } else { + echo $listEmptyMessage; + } +} + ?> diff --git a/config/haproxy-devel/haproxy_listeners_edit.php b/config/haproxy-devel/haproxy_listeners_edit.php index 2e943e96..b6d6b85d 100644 --- a/config/haproxy-devel/haproxy_listeners_edit.php +++ b/config/haproxy-devel/haproxy_listeners_edit.php @@ -106,22 +106,6 @@ function get_certificates_server($get_includeWebCert=false) { return $certificates; } -function echo_html_select($name, $keyvaluelist, $selected, $listEmptyMessage="", $onchangeEvent="") -{ - if (count($keyvaluelist)>0){ - if ($onchangeEvent != "") - $onchangeEvent .= " onchange=$onchangeEvent"; - echo ""; - } else { - echo $listEmptyMessage; - } -} - function haproxy_acl_select($mode) { global $a_acltypes; diff --git a/config/haproxy-devel/haproxy_pool_edit.php b/config/haproxy-devel/haproxy_pool_edit.php index 3ed0b799..c3707903 100644 --- a/config/haproxy-devel/haproxy_pool_edit.php +++ b/config/haproxy-devel/haproxy_pool_edit.php @@ -30,6 +30,7 @@ */ require("guiconfig.inc"); +require_once("haproxy.inc"); $d_haproxyconfdirty_path = $g['varrun_path'] . "/haproxy.conf.dirty"; @@ -48,13 +49,13 @@ if (isset($_GET['dup'])) $id = $_GET['dup']; global $simplefields; -$simplefields = array("retries","balance","connection_timeout","server_timeout", "stats_enabled","stats_username","stats_password","stats_uri","stats_realm","stats_admin","stats_node_enabled","stats_node","stats_desc","stats_refresh"); +$simplefields = array( +"name","cookie","balance", +"check_type","checkinter","httpcheck_method","monitor_uri","monitor_httpversion","monitor_username","monitor_domain", +"connection_timeout","server_timeout","retries", +"stats_enabled","stats_username","stats_password","stats_uri","stats_realm","stats_admin","stats_node_enabled","stats_node","stats_desc","stats_refresh"); if (isset($id) && $a_pools[$id]) { - $pconfig['name'] = $a_pools[$id]['name']; - $pconfig['checkinter'] = $a_pools[$id]['checkinter']; - $pconfig['monitor_uri'] = $a_pools[$id]['monitor_uri']; - $pconfig['cookie'] = $a_pools[$id]['cookie']; $pconfig['advanced'] = base64_decode($a_pools[$id]['advanced']); $pconfig['advanced_backend'] = base64_decode($a_pools[$id]['advanced_backend']); $pconfig['a_servers']=&$a_pools[$id]['ha_servers']['item']; @@ -87,7 +88,10 @@ if ($_POST) { if (preg_match("/[^a-zA-Z0-9\.\-_]/", $_POST['name'])) $input_errors[] = "The field 'Name' contains invalid characters."; - + + if ($_POST['checkinter'] !== "" && !is_numeric($_POST['checkinter'])) + $input_errors[] = "The field 'Check frequency' value is not a number."; + if ($_POST['connection_timeout'] !== "" && !is_numeric($_POST['connection_timeout'])) $input_errors[] = "The field 'Connection timeout' value is not a number."; @@ -216,13 +220,21 @@ include("head.inc"); row_helper(); +// 'processing' done, make all simple fields usable in html. +foreach($simplefields as $field){ + $pconfig[$field] = htmlspecialchars($pconfig[$field]); +} ?> - + @@ -456,20 +481,6 @@ row_helper(); - - Check freq - - size="20"> milliseconds -
For HTTP/HTTPS defaults to 1000 if left blank. For TCP no check will be performed if left empty. - - - - Health check URI - - size="64"> -
Defaults to / if left blank. - - Per server pass thru @@ -488,7 +499,74 @@ row_helper(); - + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Health checking
Health check method +
+ +
Check frequency + size="20"> milliseconds +
For HTTP/HTTPS defaults to 1000 if left blank. For TCP no check will be performed if left empty. +
Http check method + +
OPTIONS is the method usually best to perform server checks, HEAD and GET can also be used +
Http check URI + size="64"> +
Defaults to / if left blank. +
Http check version + size="64"> +
Defaults to "HTTP/1.0" if left blank. + Note that the Host field is mandatory in HTTP/1.1, and as a trick, it is possible to pass it + after "\r\n" following the version string like this:
+     "HTTP/1.1\r\nHost:\ www"
+ Also some hosts might require an accept parameter like this:
+     "HTTP/1.0\r\nHost:\ webservername:8080\r\nAccept:\ */*" +
Check with Username + size="64" onchange="updatevisibility();" onkeyup="updatevisibility();"> +
+ This is the username which will be used when connecting to MySQL/PostgreSQL server. +
+USE mysql;
+CREATE USER ''@'<pfSenseIP>';
+FLUSH PRIVILEGES;
+
Domain + size="64"> +

@@ -548,7 +626,7 @@ set by the 'retries' parameter. @@ -557,7 +635,7 @@ set by the 'retries' parameter. @@ -615,6 +693,10 @@ set by the 'retries' parameter.
Stats Username - size="64"> + size="64">
size="64">