From 6074075ce90404997f21f5019c743ce599a1c3fc Mon Sep 17 00:00:00 2001 From: PiBa-NL Date: Thu, 14 Mar 2013 23:18:41 +0100 Subject: haproxy-devel, made frontend merging in such a way that it is more obvious that a lot of settings are not needed for 'secondary' frontends. --- config/haproxy-devel/haproxy.inc | 138 +++++++++++++++++-- config/haproxy-devel/haproxy_listeners.php | 168 ++++++++++++++---------- config/haproxy-devel/haproxy_listeners_edit.php | 91 +++++++++---- config/haproxy-devel/haproxy_pool_edit.php | 2 +- 4 files changed, 287 insertions(+), 112 deletions(-) diff --git a/config/haproxy-devel/haproxy.inc b/config/haproxy-devel/haproxy.inc index e246b8e0..a03bf219 100644 --- a/config/haproxy-devel/haproxy.inc +++ b/config/haproxy-devel/haproxy.inc @@ -348,9 +348,12 @@ function write_backend($fd, $name, $pool, $frontend) { $httpchk = "ssl-hello-chk"; } else { $backend_type = $frontend['type']; - $httpchk = "httpchk"; + if(strtolower($frontend['type']) == "http") + $httpchk = "httpchk"; + else + unset($httpchk); } - + fwrite ($fd, "\tmode\t\t\t" . $backend_type . "\n"); if($pool['balance']) @@ -392,7 +395,7 @@ function write_backend($fd, $name, $pool, $frontend) { else $uri = "/"; - if (!$sslserverpresent) + if ($httpchk) fwrite ($fd, "\toption\t\t\t{$httpchk} HEAD " . $uri . " HTTP/1.0\n"); if ($pool['advanced_backend']) { @@ -451,7 +454,7 @@ function haproxy_configure() { function haproxy_check_writtenconfig_error() { $configcheckoutput = shell_exec("haproxy -c -V -f /var/etc/haproxy.cfg 2>&1"); if (!strstr($configcheckoutput, "Configuration file is valid")) - return $configcheckoutput; + return str_replace("\n","
\n", $configcheckoutput); else return false; } @@ -528,12 +531,16 @@ function haproxy_writeconf() { $b = &$a_bind[$bname]; // Overwrite ? - $b['type'] = $backend['type']; - $b['forwardfor'] = $backend['forwardfor']; - $b['httpclose'] = $backend['httpclose']; - $b['max_connections'] = $backend['max_connections']; - $b['client_timeout'] = $backend['client_timeout']; - $b['advanced'] = $backend['advanced']; + if ($backend['secondary'] != 'yes') { + if (isset($b['type'])) + $input_errors[] = "Multiple primary frondends for $bname"; + $b['type'] = $backend['type']; + $b['forwardfor'] = $backend['forwardfor']; + $b['httpclose'] = $backend['httpclose']; + $b['max_connections'] = $backend['max_connections']; + $b['client_timeout'] = $backend['client_timeout']; + $b['advanced'] = $backend['advanced']; + } if ($ssl_crt != "") { if ($b['ssl_info'] == "") @@ -585,14 +592,12 @@ function haproxy_writeconf() { $advanced = base64_decode($bind['advanced']); fwrite($fd, "\t" . $advanced . "\n"); } - + // https is an alias for tcp for clarity purpouses if(strtolower($bind['type']) == "https") { $backend_type = "tcp"; - $httpchk = "ssl-hello-chk"; - } else { + } else { $backend_type = $bind['type']; - $httpchk = "httpchk"; } fwrite ($fd, "\tmode\t\t\t" . $backend_type . "\n"); @@ -711,6 +716,9 @@ function haproxy_writeconf() { // create config file fclose($fd); + if ($input_errors) + print_input_errors($input_errors); + if (isset($a_global['carpdev'])) haproxy_install_cron(true); else @@ -881,4 +889,106 @@ function haproxy_do_xmlrpc_sync($sync_to_ip, $password) { } } +function get_frontend_id($name) { + global $a_backend; + $i = 0; + foreach($a_backend as $backend) + { + if ($backend['name'] == $name) + return $i; + $i++; + } + return null; +} + +function get_frontend_ipport($fontend) { + global $a_backend; + if ($fontend['secondary'] == 'yes') + $mainfontend = $a_backend[get_frontend_id($fontend['primary_frontend'])]; + else + $mainfontend = $fontend; + if($mainfontend['extaddr'] == "any") + $result = "0.0.0.0"; + elseif($mainfontend['extaddr']) + $result = $mainfontend['extaddr']; + else + $result = get_current_wan_address('wan'); + return $result . ":" . $mainfontend['port']; + return 'abc'; +} + +function haproxy_check_config() { + global $config; + $a_backends = &$config['installedpackages']['haproxy']['ha_backends']['item']; + $result = false; + $activefrontends = array(); + $issues = array(); + + foreach($a_backends as $frontend) { + if (($frontend['status'] != 'active') || ($frontend['secondary'] == 'yes')) + continue; + $ipport = get_frontend_ipport($frontend); + if (isset($activefrontends[$ipport])) + $issues['P_'.$ipport] = "Multiple primary frontends with IP:Port \"$ipport\""; + else + $activefrontends[$ipport] = true; + } + foreach($a_backends as $frontend) { + if (($frontend['status'] != 'active') || ($frontend['secondary'] != 'yes')) + continue; + $ipport = get_frontend_ipport($frontend); + if (!isset($activefrontends[$ipport])) + $issues['S_'.$frontend['name']] = "Secondary frontend \"{$frontend['name']}\" without active primary frontend."; + } + foreach ($issues as $item) + $result .= ($result == false ? "" : "
") . $item; + return $result; +} + +function get_haproxy_frontends($excludeitem="") { + global $config; + $a_frontend = &$config['installedpackages']['haproxy']['ha_backends']['item']; + $result = array(); + foreach($a_frontend as &$frontend) + { + if ($frontend['secondary']) + continue; + if ($frontend['name'] == $excludeitem) + continue; + + $serveradress = "{$frontend['extaddr']}:{$frontend['port']}"; + $result[$frontend['name']]['name'] = "{$frontend['name']} - {$frontend['type']} ({$serveradress})"; + $result[$frontend['name']]['ref'] = &$frontend; + } + asort($result, SORT_STRING); + return $result; +} + +function phparray_to_javascriptarray_recursive($nestID, $path, $items, $nodeName, $includeitems) { + $offset = str_repeat(' ',$nestID); + $itemName = "item$nestID"; + echo "{$offset}$nodeName = {};\n"; + if (is_array($items)) + foreach ($items as $key => $item) + { + if (in_array($path.'/'.$key, $includeitems)) + $subpath = $path.'/'.$key; + else + $subpath = $path.'/*'; + if (in_array($subpath, $includeitems) || in_array($path.'/*', $includeitems)) { + if (is_array($item)) { + $subNodeName = "item$nestID"; + phparray_to_javascriptarray_recursive($nestID+1, $subpath, $items[$key], $subNodeName, $includeitems); + echo "{$offset}{$nodeName}['{$key}'] = $itemName;\n"; + } else + echo "{$offset}{$nodeName}['$key'] = '$item';\n"; + } + } +} + +function phparray_to_javascriptarray($items, $javaMapName, $includeitems) +{ + phparray_to_javascriptarray_recursive(1,'',$items, $javaMapName, $includeitems); +} + ?> diff --git a/config/haproxy-devel/haproxy_listeners.php b/config/haproxy-devel/haproxy_listeners.php index 88cdb62f..7b4cf3da 100644 --- a/config/haproxy-devel/haproxy_listeners.php +++ b/config/haproxy-devel/haproxy_listeners.php @@ -34,6 +34,7 @@ require_once("guiconfig.inc"); $d_haproxyconfdirty_path = $g['varrun_path'] . "/haproxy.conf.dirty"; require_once("haproxy.inc"); +require_once("certs.inc"); if (!is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) { $config['installedpackages']['haproxy']['ha_backends']['item'] = array(); @@ -57,12 +58,19 @@ if ($_POST) { unlink_if_exists($d_haproxyconfdirty_path); } } +} else { + $result = haproxy_check_config($retval); + if ($result) + $savemsg = gettext($result); } +$id = $_GET['id']; +$id = get_frontend_id($id); + if ($_GET['act'] == "del") { - if (isset($a_backend[$_GET['id']])) { + if (isset($a_backend[$id])) { if (!$input_errors) { - unset($a_backend[$_GET['id']]); + unset($a_backend[$id]); write_config(); touch($d_haproxyconfdirty_path); } @@ -104,77 +112,101 @@ include("head.inc");
- - - - - - - - +
NameDescriptionAddressTypeServer pool
+ + + + + + + + + + "; - $textse = ""; + + function sort_backends(&$a, &$b) { + if ($a['ipport'] != $b['ipport']) + return $a['ipport'] > $b['ipport'] ? 1 : -1; + if ($a['secondary'] != $b['secondary']) + return $a['secondary'] > $b['secondary'] ? 1 : -1; + if ($a['name'] != $b['name']) + return $a['name'] > $b['name'] ? 1 : -1; + return 0; } -?> - - - - - - - - - - - - - - - -
PrimaryAdvancedNameDescriptionAddressTypeServer poolParent
- - - - - - - - - - - - - - - - -
-
- - - - -
-
+ foreach($a_backend as &$backend2) { + $backend2['ipport'] = get_frontend_ipport($backend2); + } + usort($a_backend,'sort_backends'); + + $certimg = "/themes/{$g['theme']}/images/icons/icon_frmfld_cert.png"; + unset($ipport_previous); + foreach ($a_backend as $backend): + $backendname = $backend['name']; + $textgray = $backend['status'] != 'active' ? " gray" : ""; + if (isset($ipport_previous ) && $backend['ipport'] != $ipport_previous): + ?> +   + + + " ondblclick="document.location='haproxy_listeners_edit.php?id=';"> + + + + + SSL offloading + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + +
- + diff --git a/config/haproxy-devel/haproxy_listeners_edit.php b/config/haproxy-devel/haproxy_listeners_edit.php index 3139250c..0826010c 100644 --- a/config/haproxy-devel/haproxy_listeners_edit.php +++ b/config/haproxy-devel/haproxy_listeners_edit.php @@ -101,18 +101,20 @@ function get_certificates_server($get_includeWebCert=false) { if ($usagestr != "") $usagestr = " (".trim($usagestr).")"; - $certificates[$cert['refid']] = $cert['descr'] . $caname . $inuse . $revoked . $usagestr; + $certificates[$cert['refid']]['name'] = $cert['descr'] . $caname . $inuse . $revoked . $usagestr; } return $certificates; } -function echo_html_select($name, $keyvaluelist, $selected, $listEmptyMessage="") +function echo_html_select($name, $keyvaluelist, $selected, $listEmptyMessage="", $onchangeEvent="") { - if (count($keyvaluelist)>0){ - echo ""; foreach($keyvaluelist as $key => $desc){ $selectedhtml = $key == $selected ? "selected" : ""; - echo ""; + echo ""; } echo ""; } else { @@ -141,7 +143,7 @@ $a_backend = &$config['installedpackages']['haproxy']['ha_backends']['item']; $a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item']; global $simplefields; -$simplefields = array('name','desc','status','secondary','type','forwardfor','httpclose','extaddr','backend_serverpool', +$simplefields = array('name','desc','status','secondary','primary_frontend','type','forwardfor','httpclose','extaddr','backend_serverpool', 'max_connections','client_timeout','port','ssloffloadcert','dcertadv','ssloffload','ssloffloadacl'); if (isset($_POST['id'])) @@ -152,6 +154,8 @@ else if (isset($_GET['dup'])) $id = $_GET['dup']; +$id = get_frontend_id($id); + if (isset($id) && $a_backend[$id]) { $pconfig['a_acl']=&$a_backend[$id]['ha_acls']['item']; $pconfig['advanced'] = base64_decode($a_backend[$id]['advanced']); @@ -193,7 +197,7 @@ if ($_POST) { /* Ensure that our pool names are unique */ for ($i=0; isset($config['installedpackages']['haproxy']['ha_backends']['item'][$i]); $i++) if (($_POST['name'] == $config['installedpackages']['haproxy']['ha_backends']['item'][$i]['name']) && ($i != $id)) - $input_errors[] = "This frontend name has already been used. Frontend names must be unique."; + $input_errors[] = "This frontend name has already been used. Frontend names must be unique. $i != $id"; $a_acl=array(); $acl_names=array(); @@ -273,7 +277,6 @@ if (!$id) $pgtitle = "HAProxy: Frontend: Edit"; include("head.inc"); - ?> @@ -281,6 +284,7 @@ include("head.inc"); .haproxy_mode_http{display:none;} .haproxy_ssloffloading_enabled{display:none;} .haproxy_primary{} + .haproxy_secondary{display:none;} @@ -445,21 +449,32 @@ include("head.inc"); function updatevisibility() { + d = document; + ssloffload = d.getElementById("ssloffload"); + type = d.getElementById("type"); + secondary = d.getElementById("secondary"); + primary_frontend = d.getElementById("primary_frontend"); + + if (secondary.checked) + type = primaryfrontends[primary_frontend.value]['ref']['type']; + else + type = d.getElementById("type").value; + setCSSdisplay(".haproxy_ssloffloading_enabled", ssloffload.checked); - setCSSdisplay(".haproxy_mode_http", type.value == "http"); + setCSSdisplay(".haproxy_mode_http", type == "http"); setCSSdisplay(".haproxy_primary", !secondary.checked); + setCSSdisplay(".haproxy_secondary", secondary.checked); + + type_change(type); } - function type_change() { - var type, d, i, j, el, row; + function type_change(type) { + var d, i, j, el, row; var count = ; var acl = [ ]; var mode = [ ]; d = document; - type = d.getElementById("type").value; - - for (i = 0; i < 99; i++) { el = d.getElementById("acl_expression" + i); row = d.getElementById("aclrow" + i); @@ -475,7 +490,6 @@ include("head.inc"); } } } - updatevisibility(); } @@ -501,25 +515,34 @@ include("head.inc"); size="64"> + + Status + + + + Shared Frontend - onclick="updatevisibility();">secondary backend
+ onclick="updatevisibility();"/> Use this setting to configure multiple backends/accesslists for a single frontend.
All settings of which only 1 can exist will be hidden.
The frontend settings will be merged into 1 set of frontend configuration. - - Status + + Primary frontend - + - - + + External address size="30" maxlength="500"> @@ -576,10 +599,10 @@ include("head.inc"); } ?> - + Type - @@ -663,7 +686,11 @@ include("head.inc");
The 'forwardfor' option creates an HTTP 'X-Forwarded-For' header which contains the client's IP address. This is useful to let the final web server - know what the client address was (eg for statistics on domains) + know what the client address was. (eg for statistics on domains)
+
+ It is important to note that as long as HAProxy does not support keep-alive connections, + only the first request of a connection will receive the header. For this reason, + it is important to ensure that option httpclose is set when using this option. @@ -744,7 +771,7 @@ include("head.inc"); - + @@ -757,6 +784,12 @@ include("head.inc");
+