net/haproxy: implement seamless reloads, closes #224

This commit is contained in:
Frank Wall
2018-08-02 21:50:36 +02:00
parent 55ac7b5581
commit 7b99ffd0fd
8 changed files with 57 additions and 15 deletions
@@ -40,7 +40,7 @@ use \OPNsense\HAProxy\HAProxy;
class ServiceController extends ApiMutableServiceControllerBase
{
static protected $internalServiceClass = '\OPNsense\HAProxy\HAProxy';
static protected $internalServiceTemplate = 'OPNsense/Haproxy';
static protected $internalServiceTemplate = 'OPNsense/HAProxy';
static protected $internalServiceEnabled = 'general.enabled';
static protected $internalServiceName = 'haproxy';
@@ -60,4 +60,12 @@ class ServiceController extends ApiMutableServiceControllerBase
$response = $backend->configdRun("haproxy configtest");
return array("result" => $response);
}
/**
* reconfigure force restart check, return zero for soft-reload
*/
protected function reconfigureForceRestart()
{
return 0;
}
}
@@ -9,10 +9,16 @@
</field>
<field>
<id>haproxy.general.gracefulStop</id>
<label>Graceful Stop</label>
<label>Graceful stop</label>
<type>checkbox</type>
<help><![CDATA[Enable HAProxy's graceful stop mode. In this mode HAProxy will continue to process existing connections until they close. Note that this may severely slow down HAProxy's shutdown, depending on the configured timeout values. If graceful stop mode is not enabled, HAProxy will use the hard stop mode where it immediately quits and all established connections are closed. Hard stop mode is recommended.]]></help>
</field>
<field>
<id>haproxy.general.seamlessReload</id>
<label>Seamless reload</label>
<type>checkbox</type>
<help><![CDATA[HAProxy will handle service restarts in a way that no connections are dropped. This is the best restart mode, because it has no impact on user experience. That being said, there might be edge cases where seamless reloads lead to unexpected behaviour.]]></help>
</field>
<field>
<id>haproxy.general.showIntro</id>
<label>Show introduction pages</label>
@@ -1,6 +1,6 @@
<model>
<mount>//OPNsense/HAProxy</mount>
<version>2.3.0</version>
<version>2.4.0</version>
<description>
the HAProxy load balancer
</description>
@@ -14,6 +14,10 @@
<default>0</default>
<Required>Y</Required>
</gracefulStop>
<seamlessReload type="BooleanField">
<default>0</default>
<Required>Y</Required>
</seamlessReload>
<showIntro type="BooleanField">
<default>1</default>
</showIntro>
@@ -340,22 +340,20 @@ POSSIBILITY OF SUCH DAMAGE.
$(this).click(function(){
var frm_id = $(this).closest("form").attr("id");
var frm_title = $(this).closest("form").attr("data-title");
// set progress animation
$("#"+frm_id+"_progress").addClass("fa fa-spinner fa-pulse");
// save data for tab
saveFormToEndpoint(url="/api/haproxy/settings/set",formid=frm_id,callback_ok=function(){
// set progress animation when reloading
$("#"+frm_id+"_progress").addClass("fa fa-spinner fa-pulse");
// on correct save, perform reconfigure
ajaxCall(url="/api/haproxy/service/reconfigure", sendData={}, callback=function(data,status){
// when done, disable progress animation.
$("#"+frm_id+"_progress").removeClass("fa fa-spinner fa-pulse");
if (status != "success" || data['status'] != 'ok' ) {
// fix error handling
ajaxCall(url="/api/haproxy/service/reconfigure", sendData={}, callback=function(data,status) {
if (status != "success" || data['status'] != 'ok') {
BootstrapDialog.show({
type:BootstrapDialog.TYPE_WARNING,
title: frm_title,
message: JSON.stringify(data),
type: BootstrapDialog.TYPE_WARNING,
title: "{{ lang._('Error reconfiguring HAProxy') }}",
message: data['status'],
draggable: true
});
} else {
@@ -363,7 +361,10 @@ POSSIBILITY OF SUCH DAMAGE.
updateServiceStatusUI(data['status']);
});
}
// when done, disable progress animation.
$("#"+frm_id+"_progress").removeClass("fa fa-spinner fa-pulse");
});
});
});
});
@@ -7,11 +7,18 @@ fi
rcprefix=
case "$1" in
stop|restart)
stop)
if [ "${haproxy_hardstop}" == "YES" ]; then
rcprefix="hard"
fi
;;
reload)
if [ "${haproxy_softreload}" == "YES" ]; then
rcprefix="soft"
elif [ "${haproxy_hardstop}" == "YES" ]; then
rcprefix="hard"
fi
;;
esac
/usr/local/etc/rc.d/haproxy ${rcprefix}${1}
@@ -22,6 +22,12 @@ parameters:
type:script
message:restarting haproxy
[reload]
command:/usr/local/opnsense/scripts/OPNsense/HAProxy/setup.sh; /usr/local/opnsense/scripts/OPNsense/HAProxy/rc-wrapper.sh reload || /usr/local/opnsense/scripts/OPNsense/HAProxy/rc-wrapper.sh restart
parameters:
type:script
message:reloading haproxy
[configtest]
command:/usr/local/etc/rc.d/haproxy configtest 2>&1 || exit 0
parameters:
@@ -623,7 +623,11 @@ global
gid 80
chroot /var/haproxy
daemon
{% if helpers.exists('OPNsense.HAProxy.general.seamlessReload') and OPNsense.HAProxy.general.seamlessReload|default("0") == "1" %}
stats socket /var/run/haproxy.socket level admin expose-fd listeners
{% else %}
stats socket /var/run/haproxy.socket level admin
{% endif %}
nbproc {{OPNsense.HAProxy.general.tuning.nbproc}}
{% if helpers.exists('OPNsense.HAProxy.general.tuning.maxConnections') %}
maxconn {{OPNsense.HAProxy.general.tuning.maxConnections}}
@@ -8,6 +8,12 @@ haproxy_hardstop=NO
{% else %}
haproxy_hardstop=YES
{% endif %}
{% if helpers.exists('OPNsense.HAProxy.general.seamlessReload') and OPNsense.HAProxy.general.seamlessReload|default("0") == "1" %}
haproxy_socket="/var/run/haproxy.socket"
haproxy_softreload=YES
{% else %}
haproxy_softreload=NO
{% endif %}
{% else %}
haproxy_enable=NO
{% endif %}