From 5e7ae930c527a72e16765fdfc44c9892cc26b744 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 7 Nov 2019 11:25:13 +0100 Subject: [PATCH] =?UTF-8?q?N=C2=B02240=20-=20Supportability=20-=20Maintena?= =?UTF-8?q?nce=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- approot.inc.php | 2 ++ index.php | 31 +----------------- setup/setuppage.class.inc.php | 3 +- setup/setuputils.class.inc.php | 4 +-- webservices/cron.php | 59 +++++++++++++++++----------------- 5 files changed, 37 insertions(+), 62 deletions(-) diff --git a/approot.inc.php b/approot.inc.php index fbcb4879c..45af5d77e 100644 --- a/approot.inc.php +++ b/approot.inc.php @@ -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'): diff --git a/index.php b/index.php index 8d7384d92..fde7078ff 100644 --- a/index.php +++ b/index.php @@ -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 diff --git a/setup/setuppage.class.inc.php b/setup/setuppage.class.inc.php index 02b0af6d4..808be36dd 100644 --- a/setup/setuppage.class.inc.php +++ b/setup/setuppage.class.inc.php @@ -284,7 +284,8 @@ CSS public function output() { - $this->s_content = "

 ".htmlentities($this->s_title, + $sLogo = utils::GetAbsoluteUrlAppRoot().'/images/itop-logo.png'; + $this->s_content = "

\" ".htmlentities($this->s_title, ENT_QUOTES, self::PAGES_CHARSET)."

\n
{$this->s_content}\n
\n"; return parent::output(); diff --git a/setup/setuputils.class.inc.php b/setup/setuputils.class.inc.php index 1cca800a2..1422cb620 100644 --- a/setup/setuputils.class.inc.php +++ b/setup/setuputils.class.inc.php @@ -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) diff --git a/webservices/cron.php b/webservices/cron.php index 1b56450d2..ecf26cd46 100644 --- a/webservices/cron.php +++ b/webservices/cron.php @@ -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()) + /** @var BackgroundTask $oTask */ + 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,18 +219,26 @@ 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()) { $aTasks[$oTask->Get('class_name')] = $oTask; } - + $oNow = new DateTime(); ReorderProcesses($aProcesses, $aTasks, $oNow, $bVerbose, $oP); - + 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,24 +568,21 @@ try { $oConfig = utils::GetConfig(); $oMutex = new iTopMutex('cron'); - if ($oMutex->TryLock()) + if (!MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE)) { - // 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); - } - - CronExec($oP, $aProcesses, $bVerbose); + $oP->p("A maintenance is ongoing"); } else { - // Exit silently - $oP->p("Already running..."); + if ($oMutex->TryLock()) + { + CronExec($oP, $aProcesses, $bVerbose); + } + else + { + // Exit silently + $oP->p("Already running..."); + } } } catch (Exception $e)