mirror of
https://github.com/netbirdio/plugins.git
synced 2026-05-22 18:44:07 -07:00
add pre-defined cron jobs to maintenance page
This commit is contained in:
@@ -23,6 +23,7 @@ Added:
|
||||
* add support for server templates (#1975)
|
||||
* add support for additional resolver options (#1975)
|
||||
* add support for resolve-prefer option (#1975)
|
||||
* add pre-defined cron jobs to maintenance page
|
||||
|
||||
Fixed:
|
||||
* prevent service outage by aborting "Apply" when configtest fails
|
||||
|
||||
+102
-2
@@ -31,16 +31,21 @@
|
||||
|
||||
namespace OPNsense\HAProxy\Api;
|
||||
|
||||
use OPNsense\Base\ApiControllerBase;
|
||||
use OPNsense\Base\ApiMutableModelControllerBase;
|
||||
use OPNsense\Core\Backend;
|
||||
use OPNsense\Core\Config;
|
||||
use OPNsense\Cron\Cron;
|
||||
use OPNsense\HAProxy\HAProxy;
|
||||
|
||||
/**
|
||||
* Class MaintenanceController
|
||||
* @package OPNsense\HAProxy
|
||||
*/
|
||||
class MaintenanceController extends ApiControllerBase
|
||||
class MaintenanceController extends ApiMutableModelControllerBase
|
||||
{
|
||||
protected static $internalModelName = 'haproxy';
|
||||
protected static $internalModelClass = '\OPNsense\HAProxy\HAProxy';
|
||||
|
||||
/**
|
||||
* jQuery bootstrap certificates diff list
|
||||
* @return array|mixed
|
||||
@@ -268,4 +273,99 @@ class MaintenanceController extends ApiControllerBase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* create new cron job or return already available one
|
||||
* @return array status action
|
||||
*/
|
||||
public function fetchCronIntegrationAction()
|
||||
{
|
||||
$result = array("result" => "no change");
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$mdlHaproxy = $this->getModel();
|
||||
$backend = new Backend();
|
||||
|
||||
// Define possible cron jobs with their configd actions
|
||||
$cronjobs = array(
|
||||
'syncCerts' => 'cert_sync_bulk',
|
||||
'updateOcsp' => 'update_ocsp',
|
||||
'reloadService' => 'reload',
|
||||
'restartService' => 'restart',
|
||||
);
|
||||
|
||||
// Iterate over all possible cron jobs
|
||||
foreach ($cronjobs as $cron => $cron_action) {
|
||||
|
||||
// Name of the item that holds the cron UUID
|
||||
$cron_ref = "${cron}Cron";
|
||||
|
||||
// Check if the cron job is enabled or disabled
|
||||
if ((string)$mdlHaproxy->maintenance->cronjobs->$cron == "1") {
|
||||
// Check if a cron job already exists
|
||||
if ((string)$mdlHaproxy->maintenance->cronjobs->$cron_ref == "") {
|
||||
|
||||
// Create new cron job
|
||||
$mdlCron = new Cron();
|
||||
// NOTE: Only configd actions are valid commands for cronjobs
|
||||
// and they *must* provide a description that is not empty.
|
||||
$cron_uuid = $mdlCron->newDailyJob(
|
||||
"HAProxy",
|
||||
"haproxy ${cron_action}",
|
||||
"Added by HAProxy plugin",
|
||||
"*",
|
||||
"1"
|
||||
);
|
||||
$mdlHaproxy->maintenance->cronjobs->$cron_ref = $cron_uuid;
|
||||
|
||||
// Save updated configuration.
|
||||
if ($mdlCron->performValidation()->count() == 0) {
|
||||
$mdlCron->serializeToConfig();
|
||||
// save data to config, do not validate because the current in memory model doesn't know about the
|
||||
// cron item just created.
|
||||
$mdlHaproxy->serializeToConfig($validateFullModel = false, $disable_validation = true);
|
||||
Config::getInstance()->save();
|
||||
// Refresh the crontab
|
||||
$backend->configdRun('template reload OPNsense/Cron');
|
||||
// (res)start daemon
|
||||
$backend->configdRun("cron restart");
|
||||
$this->getLogger()->error("HAProxy: successfully created cron job $cron ($cron_uuid)");
|
||||
$result['result'] = "new";
|
||||
$result['uuid'] = $cron_uuid;
|
||||
} else {
|
||||
$this->getLogger()->error("HAProxy: unable to create cron job $cron");
|
||||
$result['result'] = "unable to add cron";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check if a cron job exists
|
||||
if ((string)$mdlHaproxy->maintenance->cronjobs->$cron_ref != "") {
|
||||
|
||||
// Clean existin entry
|
||||
$cron_uuid = (string)$mdlHaproxy->maintenance->cronjobs->$cron_ref;
|
||||
$mdlHaproxy->maintenance->cronjobs->$cron_ref = "";
|
||||
|
||||
// Delete the cronjob item
|
||||
$mdlCron = new Cron();
|
||||
if ($mdlCron->jobs->job->del($cron_uuid)) {
|
||||
// If item is removed, serialize to config and save
|
||||
$mdlCron->serializeToConfig();
|
||||
$mdlHaproxy->serializeToConfig($validateFullModel = false, $disable_validation = true);
|
||||
Config::getInstance()->save();
|
||||
// Regenerate the crontab
|
||||
$backend->configdRun('template reload OPNsense/Cron');
|
||||
// (res)start daemon
|
||||
$backend->configdRun("cron restart");
|
||||
$this->getLogger()->error("HAProxy: successfully deleted cron job $cron ($cron_uuid)");
|
||||
$result['result'] = "deleted";
|
||||
} else {
|
||||
$this->getLogger()->error("HAProxy: unable to delete cron job $cron ($cron_uuid)");
|
||||
$result['result'] = "unable to delete cron";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -41,5 +41,6 @@ class MaintenanceController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
// choose template
|
||||
$this->view->pick('OPNsense/HAProxy/maintenance');
|
||||
$this->view->maintenanceCronjobsForm = $this->getForm("maintenanceCronjobs");
|
||||
}
|
||||
}
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
<form>
|
||||
<field>
|
||||
<label>Sync SSL certificate changes</label>
|
||||
<type>header</type>
|
||||
<style>table_cron table_cron_syncCerts</style>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.maintenance.cronjobs.syncCerts</id>
|
||||
<label>Enable</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Periodically sync SSL certificate changes into the running HAProxy service. This is most useful when using short-lived Let's Encrypt certificates, but changes to other certificates will also be synced. Note that when using the Let's Encrypt plugin, it is also possible to use an <a target="_blank" href="/ui/acmeclient/actions">Automation</a> instead of this cron job.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Update OCSP data for SSL certificates</label>
|
||||
<type>header</type>
|
||||
<style>table_cron table_cron_updateOcsp</style>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.maintenance.cronjobs.updateOcsp</id>
|
||||
<label>Enable</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Periodically fetch OCSP data for all configured SSL certificates. Note that OCSP support needs to be enabled in <a target="_blank" href="/ui/haproxy#general-settings">HAProxy service settings</a>.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Reload HAProxy service</label>
|
||||
<type>header</type>
|
||||
<style>table_cron table_cron_reloadService</style>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.maintenance.cronjobs.reloadService</id>
|
||||
<label>Enable</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Periodically perform a reload of the HAProxy service. This may cause a minor service disruption, depending on the configuration. A nightly reload could be used to apply configuration changes outside of business hours, or to workaround a bug.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Restart HAProxy service</label>
|
||||
<type>header</type>
|
||||
<style>table_cron table_cron_restartService</style>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.maintenance.cronjobs.restartService</id>
|
||||
<label>Enable</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Periodically perform a full restart of the HAProxy service. This will cause a notable service disruption. A full restart is required in some cases where a reload does not work as expected (i.e. due to long-running connections and very high timeout values).]]></help>
|
||||
</field>
|
||||
</form>
|
||||
@@ -2815,5 +2815,81 @@
|
||||
</hostname>
|
||||
</mailer>
|
||||
</mailers>
|
||||
<maintenance>
|
||||
<cronjobs>
|
||||
<syncCerts type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
</syncCerts>
|
||||
<syncCertsCron type="ModelRelationField">
|
||||
<Model>
|
||||
<queues>
|
||||
<source>OPNsense.Cron.Cron</source>
|
||||
<items>jobs.job</items>
|
||||
<display>description</display>
|
||||
<filters>
|
||||
<origin>/HAProxy/</origin>
|
||||
</filters>
|
||||
</queues>
|
||||
</Model>
|
||||
<ValidationMessage>Related cron not found.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</syncCertsCron>
|
||||
<updateOcsp type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
</updateOcsp>
|
||||
<updateOcspCron type="ModelRelationField">
|
||||
<Model>
|
||||
<queues>
|
||||
<source>OPNsense.Cron.Cron</source>
|
||||
<items>jobs.job</items>
|
||||
<display>description</display>
|
||||
<filters>
|
||||
<origin>/HAProxy/</origin>
|
||||
</filters>
|
||||
</queues>
|
||||
</Model>
|
||||
<ValidationMessage>Related cron not found.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</updateOcspCron>
|
||||
<reloadService type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
</reloadService>
|
||||
<reloadServiceCron type="ModelRelationField">
|
||||
<Model>
|
||||
<queues>
|
||||
<source>OPNsense.Cron.Cron</source>
|
||||
<items>jobs.job</items>
|
||||
<display>description</display>
|
||||
<filters>
|
||||
<origin>/HAProxy/</origin>
|
||||
</filters>
|
||||
</queues>
|
||||
</Model>
|
||||
<ValidationMessage>Related cron not found.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</reloadServiceCron>
|
||||
<restartService type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
</restartService>
|
||||
<restartServiceCron type="ModelRelationField">
|
||||
<Model>
|
||||
<queues>
|
||||
<source>OPNsense.Cron.Cron</source>
|
||||
<items>jobs.job</items>
|
||||
<display>description</display>
|
||||
<filters>
|
||||
<origin>/HAProxy/</origin>
|
||||
</filters>
|
||||
</queues>
|
||||
</Model>
|
||||
<ValidationMessage>Related cron not found.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</restartServiceCron>
|
||||
</cronjobs>
|
||||
</maintenance>
|
||||
</items>
|
||||
</model>
|
||||
|
||||
@@ -28,6 +28,72 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#}
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
|
||||
// Get cronjobs
|
||||
var cronjobs_data_get_map = {'frm_cronjobs':"/api/haproxy/maintenance/get"};
|
||||
// load initial data
|
||||
mapDataToFormUI(cronjobs_data_get_map).done(function(data){
|
||||
// Add link to cron job edit page: First iterate over all cron settings.
|
||||
// FIXME: Oh boy, this is ugly. Should be refactored.
|
||||
$.each(data.frm_cronjobs.haproxy.maintenance.cronjobs, function(key, value) {
|
||||
// Check if cron setting is enabled.
|
||||
if (value == 1) {
|
||||
// Find the matching cron job reference.
|
||||
cron_cfg = key + 'Cron';
|
||||
$.each(data.frm_cronjobs.haproxy.maintenance.cronjobs, function(cronkey, cronvalue) {
|
||||
// Check if it is the correct entry for this cron setting.
|
||||
if (cronkey == cron_cfg) {
|
||||
// Get the cron job UUID.
|
||||
$.each(cronvalue, function(refkey, refvalue) {
|
||||
// Only the "selected" item belongs to this entry.
|
||||
if (refvalue.selected == 1) {
|
||||
// Find the correct container for this cron setting.
|
||||
content_id = "[id=\"haproxy.maintenance.cronjobs." + key + "\"]";
|
||||
$(content_id).each(function(){
|
||||
// Finally add the link to the cron job edit page.
|
||||
cron_link = "<br><a href=\"/ui/cron/item/open/" + refkey + "\">{{ lang._('Configure cron job') }}</a>";
|
||||
$(this).closest("td").append(cron_link);
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
formatTokenizersUI();
|
||||
$('.selectpicker').selectpicker('refresh');
|
||||
});
|
||||
|
||||
// Save & reconfigure cron to activate changes
|
||||
$('[id*="saveAndReconfigureAct"]').each(function(){
|
||||
$(this).click(function(){
|
||||
// set progress animation
|
||||
$('[id*="saveAndReconfigureAct_progress"]').each(function(){
|
||||
$(this).addClass("fa fa-spinner fa-pulse");
|
||||
});
|
||||
|
||||
// extract the form id from the button id
|
||||
var frm_id = "frm_" + $(this).attr("id").split('_')[1]
|
||||
|
||||
// save data for this tab
|
||||
saveFormToEndpoint(url="/api/haproxy/maintenance/set",formid=frm_id,callback_ok=function(){
|
||||
// Handle cron integration
|
||||
ajaxCall(url="/api/haproxy/maintenance/fetchCronIntegration", sendData={}, callback=function(data,status) {
|
||||
});
|
||||
|
||||
// when done, disable progress animation
|
||||
$('[id*="saveAndReconfigureAct_progress"]').each(function(){
|
||||
$(this).removeClass("fa fa-spinner fa-pulse");
|
||||
// reload page to show or hide links to cron edit page
|
||||
setTimeout(function () {
|
||||
window.location.reload(true)
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// grid-certificates
|
||||
function syncErrorMessage(modified, deleted) {
|
||||
message = ``;
|
||||
@@ -440,8 +506,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
</script>
|
||||
|
||||
<ul class="nav nav-tabs" role="tablist" id="maintabs">
|
||||
<li class="active"><a data-toggle="tab" href="#server"><b>{{ lang._('Server') }}</b></a></li>
|
||||
<li class="active"><a data-toggle="tab" href="#server"><b>{{ lang._('Servers') }}</b></a></li>
|
||||
<li><a data-toggle="tab" href="#ssl-certs"><b>{{ lang._('SSL Certificates') }}</b></a></li>
|
||||
<li><a data-toggle="tab" href="#cronjobs"><b>{{ lang._('Cron Jobs') }}</b></a></li>
|
||||
</ul>
|
||||
|
||||
<div class="content-box tab-content">
|
||||
@@ -514,6 +581,21 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="cronjobs" class="tab-pane fade in">
|
||||
<div class="content-box" style="padding-bottom: 1.5em;">
|
||||
{{ partial("layout_partials/base_form",['fields':maintenanceCronjobsForm,'id':'frm_cronjobs'])}}
|
||||
<div class="col-md-12">
|
||||
<hr />
|
||||
<button class="btn btn-primary" id="saveAndReconfigureAct_cronjobs" type="button"><b>{{ lang._('Apply') }}</b> <i id="saveAndReconfigureAct_progress"></i></button>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<br/>
|
||||
{{ lang._('%sNOTE:%s When enabling multiple cron jobs, please adjust them so that they do not run at the same time. Check the %scron settings page%s for more cron job details and additional customization options.') | format('<b>', '</b>', '<a href="/ui/cron">', '</a>') }}
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ partial("layout_partials/base_dialog_processing") }}
|
||||
|
||||
Reference in New Issue
Block a user