N°2240 - Supportability - Maintenance mode

This commit is contained in:
Eric
2019-11-07 11:25:13 +01:00
parent 541226356c
commit 5e7ae930c5
5 changed files with 37 additions and 62 deletions

View File

@@ -33,6 +33,7 @@ if (file_exists(MAINTENANCE_MODE_FILE) && !$bBypassMaintenance)
http_response_code(503);
// Display message depending on the request
include(APPROOT.'application/maintenancemsg.php');
$sSAPIName = strtoupper(trim(php_sapi_name()));
switch (true)
{
@@ -40,6 +41,7 @@ if (file_exists(MAINTENANCE_MODE_FILE) && !$bBypassMaintenance)
_MaintenanceHtmlMessage($sMessage);
break;
case $sSAPIName == 'CLI':
case array_key_exists('HTTP_X_COMBODO_AJAX', $_SERVER):
case isset($_SERVER['REQUEST_URI']) && EndsWith($_SERVER['REQUEST_URI'], '/webservices/soapserver.php'):
case isset($_SERVER['REQUEST_URI']) && EndsWith($_SERVER['REQUEST_URI'], '/webservices/rest.php'):

View File

@@ -3,36 +3,7 @@ $sConfigFile = 'conf/production/config-itop.php';
$sStartPage = './pages/UI.php';
$sSetupPage = './setup/index.php';
//
// Maintenance mode
//
define('APPROOT', dirname(__FILE__).'/');
define('MAINTENANCE_MODE_FILE', APPROOT.'data/.maintenance');
// Use 'maintenance' parameter to bypass maintenance mode
if (!isset($bBypassMaintenance))
{
$bBypassMaintenance = isset($_REQUEST['maintenance']) ? boolval($_REQUEST['maintenance']) : false;
}
if (file_exists(MAINTENANCE_MODE_FILE) && !$bBypassMaintenance)
{
http_response_code(503);
echo 'This application is currently under maintenance';
exit();
}
/**
* helper to test if a string ends with another
* @param $haystack
* @param $needle
*
* @return bool
*/
function EndsWith($haystack, $needle) {
return substr_compare($haystack, $needle, -strlen($needle)) === 0;
}
require_once('approot.inc.php');
/**
* Check that the configuration file exists and has the appropriate access rights

View File

@@ -284,7 +284,8 @@ CSS
public function output()
{
$this->s_content = "<div id=\"header\"><h1><a href=\"http://www.combodo.com/itop\" target=\"_blank\"><img title=\"iTop by Combodo\" src=\"../images/itop-logo.png?t=".utils::GetCacheBusterTimestamp()."\"></a>&nbsp;".htmlentities($this->s_title,
$sLogo = utils::GetAbsoluteUrlAppRoot().'/images/itop-logo.png';
$this->s_content = "<div id=\"header\"><h1><a href=\"http://www.combodo.com/itop\" target=\"_blank\"><img title=\"iTop by Combodo\" alt=\" \" src=\"{$sLogo}?t=".utils::GetCacheBusterTimestamp()."\"></a>&nbsp;".htmlentities($this->s_title,
ENT_QUOTES, self::PAGES_CHARSET)."</h1>\n</div><div id=\"setup\">{$this->s_content}\n</div>\n";
return parent::output();

View File

@@ -1902,7 +1902,7 @@ EOF
);
$iCount = 1;
$iStarted = time();
$iMaxDuration = $oConfig->Get('cron_max_execution_time') + 1;
$iMaxDuration = $oConfig->Get('cron_max_execution_time');
$iTimeLimit = $iStarted + $iMaxDuration;
while ($oMutex->IsLocked())
{
@@ -1911,7 +1911,7 @@ EOF
sleep(1);
if (time() > $iTimeLimit)
{
throw new Exception("Cannot enter $sMode mode");
throw new Exception("Cannot enter $sMode mode, consider stopping the cron temporarily");
}
}
} catch (Exception $e)

View File

@@ -174,9 +174,8 @@ function CronExec($oP, $aProcesses, $bVerbose)
$oSearch = new DBObjectSearch('BackgroundTask');
/** @var DBObjectSet $oTasks */
$oTasks = new DBObjectSet($oSearch);
while (
/** @var BackgroundTask $oTask */
$oTask = $oTasks->Fetch())
while ($oTask = $oTasks->Fetch())
{
$sTaskClass = $oTask->Get('class_name');
// The BackgroundTask can point to a non existing class : this could happen for example if an extension has been removed
@@ -220,6 +219,13 @@ function CronExec($oP, $aProcesses, $bVerbose)
$oSearch = new DBObjectSearch('BackgroundTask');
while (time() < $iTimeLimit)
{
// Maintenance or ReadOnly mode
if (file_exists(MAINTENANCE_MODE_FILE) || !MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE))
{
$oP->p("Maintenance detected, exiting");
return;
}
$oTasks = new DBObjectSet($oSearch);
$aTasks = array();
while ($oTask = $oTasks->Fetch())
@@ -232,6 +238,7 @@ function CronExec($oP, $aProcesses, $bVerbose)
foreach ($aProcesses as $oProcess)
{
$sTaskClass = get_class($oProcess);
if (!array_key_exists($sTaskClass, $aTasks))
{
@@ -272,13 +279,11 @@ function CronExec($oP, $aProcesses, $bVerbose)
try
{
$sMessage = RunTask($oProcess, $aTasks[$sTaskClass], $oNow, $iTimeLimit);
}
catch (MySQLHasGoneAwayException $e)
} catch (MySQLHasGoneAwayException $e)
{
$oP->p("ERROR : 'MySQL has gone away' thrown when processing $sTaskClass (error_code=".$e->getCode().")");
exit(EXIT_CODE_FATAL);
}
catch (ProcessFatalException $e)
} catch (ProcessFatalException $e)
{
$oP->p("ERROR : an exception was thrown when processing '$sTaskClass' (".$e->getInfoLog().")");
IssueLog::Error("Cron.php error : an exception was thrown when processing '$sTaskClass' (".$e->getInfoLog().')');
@@ -307,12 +312,6 @@ function CronExec($oP, $aProcesses, $bVerbose)
$oP->p("Sleeping");
}
sleep($iCronSleep);
// Maintenance mode
if (file_exists(MAINTENANCE_MODE_FILE))
{
$oP->p("Maintenance mode detected");
return;
}
}
if ($bVerbose)
{
@@ -350,10 +349,15 @@ function DisplayStatus($oP)
* In case the task crashes AND the previous task was very quick (less than 1 second)
* both tasks will have the same last_run_date. In this case it is important NOT to start again
* by the task that just crashed.
*
* @param iProcess[] $aProcesses
* @param BackgroundTask[] $aTasks
* @param DateTime $oNow
* @param $bVerbose
* @param Page $oP
*
* @throws \ArchivedObjectException
* @throws \CoreException
*/
function ReorderProcesses(&$aProcesses, $aTasks, $oNow, $bVerbose, &$oP)
{
@@ -564,18 +568,14 @@ try
{
$oConfig = utils::GetConfig();
$oMutex = new iTopMutex('cron');
if ($oMutex->TryLock())
{
// Note: testing this now in case some of the background processes forces the read-only mode for a while
// in that case it is better to exit with the check on reentrance (mutex)
if (!MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE))
{
$oP->p("A maintenance is ongoing");
$oP->Output();
$oMutex->Unlock();
exit(EXIT_CODE_ERROR);
}
else
{
if ($oMutex->TryLock())
{
CronExec($oP, $aProcesses, $bVerbose);
}
else
@@ -584,6 +584,7 @@ try
$oP->p("Already running...");
}
}
}
catch (Exception $e)
{
$oP->p("ERROR: '".$e->getMessage()."'");