N°2240 - Supportability - Maintenance mode

This commit is contained in:
Eric
2019-11-07 09:16:06 +01:00
parent 7d8181c44f
commit d035130d00
9 changed files with 99 additions and 27 deletions

View File

@@ -4,6 +4,7 @@ define('APPROOT', dirname(__FILE__).'/');
define('APPCONF', APPROOT.'conf/'); define('APPCONF', APPROOT.'conf/');
define('ITOP_DEFAULT_ENV', 'production'); define('ITOP_DEFAULT_ENV', 'production');
define('MAINTENANCE_MODE_FILE', APPROOT.'data/.maintenance'); define('MAINTENANCE_MODE_FILE', APPROOT.'data/.maintenance');
define('READONLY_MODE_FILE', APPROOT.'data/.readonly');
if (function_exists('microtime')) if (function_exists('microtime'))
{ {

View File

@@ -1546,6 +1546,11 @@ class Config
} }
} }
if (file_exists(READONLY_MODE_FILE))
{
$this->Set('access_mode', ACCESS_READONLY, READONLY_MODE_FILE);
}
$this->m_bLogGlobal = isset($MySettings['log_global']) ? (bool)trim($MySettings['log_global']) : DEFAULT_LOG_GLOBAL; $this->m_bLogGlobal = isset($MySettings['log_global']) ? (bool)trim($MySettings['log_global']) : DEFAULT_LOG_GLOBAL;
$this->m_bLogNotification = isset($MySettings['log_notification']) ? (bool)trim($MySettings['log_notification']) : DEFAULT_LOG_NOTIFICATION; $this->m_bLogNotification = isset($MySettings['log_notification']) ? (bool)trim($MySettings['log_notification']) : DEFAULT_LOG_NOTIFICATION;
$this->m_bLogIssue = isset($MySettings['log_issue']) ? (bool)trim($MySettings['log_issue']) : DEFAULT_LOG_ISSUE; $this->m_bLogIssue = isset($MySettings['log_issue']) ? (bool)trim($MySettings['log_issue']) : DEFAULT_LOG_ISSUE;

View File

@@ -5087,7 +5087,7 @@ abstract class MetaModel
} }
/** /**
* Determines wether the target DB is frozen or not * Determines whether the target DB is frozen or not
* *
* @return bool * @return bool
*/ */

View File

@@ -45,4 +45,4 @@ class ITopArchiveTar extends Archive_Tar
{ {
IssueLog::Warning($p_message); IssueLog::Warning($p_message);
} }
} }

View File

@@ -309,7 +309,7 @@ try
unlink(APPROOT.'data/hub/compile_authent'); unlink(APPROOT.'data/hub/compile_authent');
// Load the "production" config file to clone & update it // Load the "production" config file to clone & update it
$oConfig = new Config(APPCONF.'production/'.ITOP_CONFIG_FILE); $oConfig = new Config(APPCONF.'production/'.ITOP_CONFIG_FILE);
SetupUtils::EnterMaintenanceMode($oConfig); SetupUtils::EnterReadOnlyMode($oConfig);
$oRuntimeEnv->InitDataModel($oConfig, true /* model only */); $oRuntimeEnv->InitDataModel($oConfig, true /* model only */);
@@ -381,7 +381,7 @@ try
} }
finally finally
{ {
SetupUtils::ExitMaintenanceMode(); SetupUtils::ExitReadOnlyMode();
} }
break; break;

View File

@@ -1189,6 +1189,11 @@ class Archive_Tar extends PEAR
$p_add_dir, $p_add_dir,
$p_remove_dir $p_remove_dir
); );
if (!$v_result)
{
return false;
}
} }
} }
@@ -1211,6 +1216,7 @@ class Archive_Tar extends PEAR
*/ */
public function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $v_stored_filename = null) public function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $v_stored_filename = null)
{ {
$this->_error('Adding file:'.$p_filename);
if (!$this->_file) { if (!$this->_file) {
$this->_error('Invalid file descriptor'); $this->_error('Invalid file descriptor');
return false; return false;

View File

@@ -192,10 +192,7 @@ class ApplicationInstaller
try try
{ {
$fStart = microtime(true); $fStart = microtime(true);
if ($bSwitchToMaintenance) $this->EnterReadOnlyMode();
{
SetupUtils::EnterMaintenanceMode($this->GetConfig());
}
switch ($sStep) switch ($sStep)
{ {
case '': case '':
@@ -389,6 +386,7 @@ class ApplicationInstaller
'next-step-label' => 'Completed', 'next-step-label' => 'Completed',
'percentage-completed' => 100, 'percentage-completed' => 100,
); );
$this->ExitReadOnlyMode();
break; break;
@@ -431,10 +429,6 @@ class ApplicationInstaller
} }
finally finally
{ {
if ($bSwitchToMaintenance)
{
SetupUtils::ExitMaintenanceMode();
}
$fDuration = round(microtime(true) - $fStart, 2); $fDuration = round(microtime(true) - $fStart, 2);
SetupPage::log_info("##### STEP {$sStep} duration: {$fDuration}s"); SetupPage::log_info("##### STEP {$sStep} duration: {$fDuration}s");
} }
@@ -442,6 +436,37 @@ class ApplicationInstaller
return $aResult; return $aResult;
} }
private function EnterReadOnlyMode()
{
if ($this->GetTargetEnv() != 'production')
{
return;
}
if (SetupUtils::IsInReadOnlyMode())
{
return;
}
SetupUtils::EnterReadOnlyMode($this->GetConfig());
}
private function ExitReadOnlyMode()
{
if ($this->GetTargetEnv() != 'production')
{
return;
}
if (!SetupUtils::IsInReadOnlyMode())
{
return;
}
SetupUtils::ExitReadOnlyMode();
}
protected static function DoCopy($aCopies) protected static function DoCopy($aCopies)
{ {
$aReports = array(); $aReports = array();

View File

@@ -28,6 +28,7 @@ require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
clearstatcache(); // Make sure we know what we are doing ! clearstatcache(); // Make sure we know what we are doing !
SetupUtils::ExitMaintenanceMode(false); // Reset maintenance mode in case of problem SetupUtils::ExitMaintenanceMode(false); // Reset maintenance mode in case of problem
SetupUtils::ExitReadOnlyMode(false); // Reset readonly mode in case of problem
// Set a long (at least 4 minutes) execution time for the setup to avoid timeouts during this phase // Set a long (at least 4 minutes) execution time for the setup to avoid timeouts during this phase
ini_set('max_execution_time', max(240, ini_get('max_execution_time'))); ini_set('max_execution_time', max(240, ini_get('max_execution_time')));
// While running the setup it is desirable to see any error that may happen // While running the setup it is desirable to see any error that may happen

View File

@@ -1836,10 +1836,54 @@ EOF
return APPROOT.'log/setup-queries-'.strftime('%Y-%m-%d_%H_%M').'.sql'; return APPROOT.'log/setup-queries-'.strftime('%Y-%m-%d_%H_%M').'.sql';
} }
public final static function EnterMaintenanceMode($oConfig) public static function EnterMaintenanceMode($oConfig)
{ {
@touch(MAINTENANCE_MODE_FILE); @touch(MAINTENANCE_MODE_FILE);
self::Log("----> Entering maintenance mode"); self::Log("----> Entering maintenance mode");
self::WaitCronTermination($oConfig, "maintenance");
}
public static function ExitMaintenanceMode($bLog = true)
{
@unlink(MAINTENANCE_MODE_FILE);
if ($bLog)
{
self::Log("<---- Exiting maintenance mode");
}
}
public static function IsInMaintenanceMode()
{
return file_exists(MAINTENANCE_MODE_FILE);
}
public static function EnterReadOnlyMode($oConfig)
{
@touch(READONLY_MODE_FILE);
self::Log("----> Entering read only mode");
self::WaitCronTermination($oConfig, "read only");
}
public static function ExitReadOnlyMode($bLog = true)
{
@unlink(READONLY_MODE_FILE);
if ($bLog)
{
self::Log("<---- Exiting read only mode");
}
}
public static function IsInReadOnlyMode()
{
return file_exists(READONLY_MODE_FILE);
}
/**
* @param Config $oConfig
* @param string $sMode
*/
private static function WaitCronTermination($oConfig, $sMode)
{
try try
{ {
// Wait for cron to stop // Wait for cron to stop
@@ -1858,34 +1902,24 @@ EOF
); );
$iCount = 1; $iCount = 1;
$iStarted = time(); $iStarted = time();
$iMaxDuration = $oConfig->Get('cron_max_execution_time'); $iMaxDuration = $oConfig->Get('cron_max_execution_time') + 1;
$iTimeLimit = $iStarted + $iMaxDuration; $iTimeLimit = $iStarted + $iMaxDuration;
while ($oMutex->IsLocked()) while ($oMutex->IsLocked())
{ {
self::Log("Waiting for cron to stop ($iCount)"); self::Log("Waiting for cron to stop ($iCount)");
$iCount++; $iCount++;
sleep(10); sleep(1);
if (time() > $iTimeLimit) if (time() > $iTimeLimit)
{ {
throw new Exception("Cannot enter maintenance mode"); throw new Exception("Cannot enter $sMode mode");
} }
} }
} } catch (Exception $e)
catch(Exception $e)
{ {
// Ignore errors // Ignore errors
} }
} }
public final static function ExitMaintenanceMode($bLog = true)
{
@unlink(MAINTENANCE_MODE_FILE);
if ($bLog)
{
self::Log("<---- Exiting maintenance mode");
}
}
/** /**
* Create and store Setup authentication token * Create and store Setup authentication token
* *