mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
N°2240 - Supportability - Maintenance mode
This commit is contained in:
@@ -53,40 +53,6 @@ register_shutdown_function(function()
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Use 'maintenance' parameter to bypass maintenance mode
|
|
||||||
$bBypassMaintenance = !is_null(Utils::ReadParam('maintenance', null));
|
|
||||||
|
|
||||||
// Maintenance mode
|
|
||||||
if (file_exists(APPROOT.'.maintenance') && !$bBypassMaintenance)
|
|
||||||
{
|
|
||||||
$sMessage = 'Application is currently in maintenance';
|
|
||||||
$sTitle = 'Maintenance';
|
|
||||||
|
|
||||||
http_response_code(503);
|
|
||||||
// Display message depending on the request
|
|
||||||
switch (true)
|
|
||||||
{
|
|
||||||
case isset($_SERVER['REQUEST_URI']) && EndsWith($_SERVER['REQUEST_URI'], '/pages/ajax.searchform.php'):
|
|
||||||
_MaintenanceHtmlMessage($sMessage);
|
|
||||||
break;
|
|
||||||
|
|
||||||
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'):
|
|
||||||
_MaintenanceTextMessage($sMessage);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case isset($_SERVER['CONTENT_TYPE']) && ($_SERVER['CONTENT_TYPE'] == 'application/json'):
|
|
||||||
_MaintenanceJsonMessage($sTitle, $sMessage);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
_MaintenanceSetupPageMessage($sTitle, $sMessage);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
session_name('itop-'.md5(APPROOT));
|
session_name('itop-'.md5(APPROOT));
|
||||||
session_start();
|
session_start();
|
||||||
$sSwitchEnv = utils::ReadParam('switch_env', null);
|
$sSwitchEnv = utils::ReadParam('switch_env', null);
|
||||||
@@ -120,80 +86,3 @@ else
|
|||||||
}
|
}
|
||||||
$sConfigFile = APPCONF.$sEnv.'/'.ITOP_CONFIG_FILE;
|
$sConfigFile = APPCONF.$sEnv.'/'.ITOP_CONFIG_FILE;
|
||||||
MetaModel::Startup($sConfigFile, false /* $bModelOnly */, $bAllowCache, false /* $bTraceSourceFiles */, $sEnv);
|
MetaModel::Startup($sConfigFile, false /* $bModelOnly */, $bAllowCache, false /* $bTraceSourceFiles */, $sEnv);
|
||||||
|
|
||||||
//
|
|
||||||
// Maintenance message display functions
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use a setup page to display the maintenance message
|
|
||||||
* @param $sTitle
|
|
||||||
* @param $sMessage
|
|
||||||
*/
|
|
||||||
function _MaintenanceSetupPageMessage($sTitle, $sMessage)
|
|
||||||
{
|
|
||||||
// Web Page
|
|
||||||
@include_once(APPROOT."/setup/setuppage.class.inc.php");
|
|
||||||
if (class_exists('SetupPage'))
|
|
||||||
{
|
|
||||||
$oP = new SetupPage($sTitle);
|
|
||||||
$oP->p("<h2>$sMessage</h2>");
|
|
||||||
$oP->output();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_MaintenanceTextMessage($sMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use simple text to display the maintenance message
|
|
||||||
* @param $sMessage
|
|
||||||
*/
|
|
||||||
function _MaintenanceTextMessage($sMessage)
|
|
||||||
{
|
|
||||||
echo $sMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use a simple HTML to display the maintenance message
|
|
||||||
* @param $sMessage
|
|
||||||
*/
|
|
||||||
function _MaintenanceHtmlMessage($sMessage)
|
|
||||||
{
|
|
||||||
echo '<html><body><div>'.$sMessage.'</div></body></html>';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use a simple JSON to display the maintenance message
|
|
||||||
*
|
|
||||||
* @param $sTitle
|
|
||||||
* @param $sMessage
|
|
||||||
*/
|
|
||||||
function _MaintenanceJsonMessage($sTitle, $sMessage)
|
|
||||||
{
|
|
||||||
@include_once(APPROOT."/application/ajaxwebpage.class.inc.php");
|
|
||||||
if (class_exists('ajax_page'))
|
|
||||||
{
|
|
||||||
$oP = new ajax_page($sTitle);
|
|
||||||
$oP->add_header('Access-Control-Allow-Origin: *');
|
|
||||||
$oP->SetContentType('application/json');
|
|
||||||
$oP->add('{"code":100, "message":"'.$sMessage.'"}');
|
|
||||||
$oP->Output();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_MaintenanceTextMessage($sMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
@@ -12,4 +12,56 @@ else
|
|||||||
{
|
{
|
||||||
$fItopStarted = 1000 * time();
|
$fItopStarted = 1000 * time();
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
//
|
||||||
|
// Maintenance mode
|
||||||
|
//
|
||||||
|
|
||||||
|
// Use 'maintenance' parameter to bypass maintenance mode
|
||||||
|
if (!isset($bBypassMaintenance))
|
||||||
|
{
|
||||||
|
$bBypassMaintenance = isset($_REQUEST['maintenance']) ? boolval($_REQUEST['maintenance']) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_exists(APPROOT.'.maintenance') && !$bBypassMaintenance)
|
||||||
|
{
|
||||||
|
$sMessage = 'Application is currently in maintenance';
|
||||||
|
$sTitle = 'Maintenance';
|
||||||
|
|
||||||
|
http_response_code(503);
|
||||||
|
// Display message depending on the request
|
||||||
|
include(APPROOT.'maintenancemsg.php');
|
||||||
|
|
||||||
|
switch (true)
|
||||||
|
{
|
||||||
|
case isset($_SERVER['REQUEST_URI']) && EndsWith($_SERVER['REQUEST_URI'], '/pages/ajax.searchform.php'):
|
||||||
|
_MaintenanceHtmlMessage($sMessage);
|
||||||
|
break;
|
||||||
|
|
||||||
|
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'):
|
||||||
|
_MaintenanceTextMessage($sMessage);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case isset($_SERVER['CONTENT_TYPE']) && ($_SERVER['CONTENT_TYPE'] == 'application/json'):
|
||||||
|
_MaintenanceJsonMessage($sTitle, $sMessage);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_MaintenanceSetupPageMessage($sTitle, $sMessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|||||||
74
maintenancemsg.php
Normal file
74
maintenancemsg.php
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (C) 2010-2019 Combodo SARL
|
||||||
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Maintenance message display functions
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use a setup page to display the maintenance message
|
||||||
|
* @param $sTitle
|
||||||
|
* @param $sMessage
|
||||||
|
*/
|
||||||
|
function _MaintenanceSetupPageMessage($sTitle, $sMessage)
|
||||||
|
{
|
||||||
|
// Web Page
|
||||||
|
@include_once(APPROOT.'bootstrap.inc.php');
|
||||||
|
@include_once(APPROOT.'setup/setuppage.class.inc.php');
|
||||||
|
if (class_exists('SetupPage'))
|
||||||
|
{
|
||||||
|
$oP = new SetupPage($sTitle);
|
||||||
|
$oP->p("<h2>$sMessage</h2>");
|
||||||
|
$oP->output();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_MaintenanceTextMessage($sMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use simple text to display the maintenance message
|
||||||
|
* @param $sMessage
|
||||||
|
*/
|
||||||
|
function _MaintenanceTextMessage($sMessage)
|
||||||
|
{
|
||||||
|
echo $sMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use a simple HTML to display the maintenance message
|
||||||
|
* @param $sMessage
|
||||||
|
*/
|
||||||
|
function _MaintenanceHtmlMessage($sMessage)
|
||||||
|
{
|
||||||
|
echo '<html><body><div>'.$sMessage.'</div></body></html>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use a simple JSON to display the maintenance message
|
||||||
|
*
|
||||||
|
* @param $sTitle
|
||||||
|
* @param $sMessage
|
||||||
|
*/
|
||||||
|
function _MaintenanceJsonMessage($sTitle, $sMessage)
|
||||||
|
{
|
||||||
|
@include_once(APPROOT.'bootstrap.inc.php');
|
||||||
|
@include_once(APPROOT."/application/ajaxwebpage.class.inc.php");
|
||||||
|
if (class_exists('ajax_page'))
|
||||||
|
{
|
||||||
|
$oP = new ajax_page($sTitle);
|
||||||
|
$oP->add_header('Access-Control-Allow-Origin: *');
|
||||||
|
$oP->SetContentType('application/json');
|
||||||
|
$oP->add('{"code":100, "message":"'.$sMessage.'"}');
|
||||||
|
$oP->Output();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_MaintenanceTextMessage($sMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,16 +26,6 @@ require_once(APPROOT.'core/metamodel.class.php');
|
|||||||
|
|
||||||
utils::InitTimeZone();
|
utils::InitTimeZone();
|
||||||
|
|
||||||
// Maintenance mode
|
|
||||||
if (file_exists(APPROOT.'.maintenance'))
|
|
||||||
{
|
|
||||||
http_response_code(503);
|
|
||||||
require_once(APPROOT.'core/dict.class.inc.php');
|
|
||||||
$sMessage = Dict::S('UI:Error:MaintenanceMode', 'Application is currently in maintenance');
|
|
||||||
echo "$sMessage";
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$sModule = utils::ReadParam('exec_module', '');
|
$sModule = utils::ReadParam('exec_module', '');
|
||||||
if ($sModule == '')
|
if ($sModule == '')
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -137,7 +137,21 @@ class ApplicationInstaller
|
|||||||
|
|
||||||
return ($iOverallStatus == self::OK);
|
return ($iOverallStatus == self::OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function GetConfig()
|
||||||
|
{
|
||||||
|
$sTargetEnvironment = $this->GetTargetEnv();
|
||||||
|
$sConfigFile = APPCONF.$sTargetEnvironment.'/'.ITOP_CONFIG_FILE;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new Config($sConfigFile);
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the next step of the installation and reports about the progress
|
* Executes the next step of the installation and reports about the progress
|
||||||
* and the next step to perform
|
* and the next step to perform
|
||||||
@@ -151,7 +165,7 @@ class ApplicationInstaller
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
$fStart = microtime(true);
|
$fStart = microtime(true);
|
||||||
SetupUtils::EnterMaintenanceMode();
|
SetupUtils::EnterMaintenanceMode($this->GetConfig());
|
||||||
switch ($sStep)
|
switch ($sStep)
|
||||||
{
|
{
|
||||||
case '':
|
case '':
|
||||||
@@ -356,15 +370,11 @@ class ApplicationInstaller
|
|||||||
'next-step-label' => "Unknown setup step '$sStep'.",
|
'next-step-label' => "Unknown setup step '$sStep'.",
|
||||||
'percentage-completed' => 100,
|
'percentage-completed' => 100,
|
||||||
);
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
SetupUtils::ExitMaintenanceMode();
|
|
||||||
$fDuration = round(microtime(true) - $fStart, 2);
|
|
||||||
SetupPage::log_info("##### STEP {$sStep} duration: {$fDuration}s");
|
|
||||||
}
|
}
|
||||||
catch (Exception $e)
|
catch (Exception $e)
|
||||||
{
|
{
|
||||||
SetupUtils::ExitMaintenanceMode();
|
|
||||||
|
|
||||||
$aResult = array(
|
$aResult = array(
|
||||||
'status' => self::ERROR,
|
'status' => self::ERROR,
|
||||||
'message' => $e->getMessage(),
|
'message' => $e->getMessage(),
|
||||||
@@ -389,6 +399,12 @@ class ApplicationInstaller
|
|||||||
$idx++;
|
$idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
SetupUtils::ExitMaintenanceMode();
|
||||||
|
$fDuration = round(microtime(true) - $fStart, 2);
|
||||||
|
SetupPage::log_info("##### STEP {$sStep} duration: {$fDuration}s");
|
||||||
|
}
|
||||||
|
|
||||||
return $aResult;
|
return $aResult;
|
||||||
}
|
}
|
||||||
@@ -946,6 +962,11 @@ class ApplicationInstaller
|
|||||||
// Ready to go !!
|
// Ready to go !!
|
||||||
require_once(APPROOT.'core/dict.class.inc.php');
|
require_once(APPROOT.'core/dict.class.inc.php');
|
||||||
MetaModel::ResetCache();
|
MetaModel::ResetCache();
|
||||||
|
|
||||||
|
// Perform final setup tasks here
|
||||||
|
//
|
||||||
|
$aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), APPROOT.$sModulesDir);
|
||||||
|
$oProductionEnv->CallInstallerHandlers($aAvailableModules, $aSelectedModuleCodes, 'AfterCreateConfig');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
$bBypassMaintenance = true; // Reset maintenance mode in case of problem
|
||||||
require_once('../approot.inc.php');
|
require_once('../approot.inc.php');
|
||||||
require_once(APPROOT.'/bootstrap.inc.php');
|
require_once(APPROOT.'/bootstrap.inc.php');
|
||||||
require_once(APPROOT.'/application/utils.inc.php');
|
require_once(APPROOT.'/application/utils.inc.php');
|
||||||
@@ -26,6 +27,7 @@ require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
|
|||||||
require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
|
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
|
||||||
// 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
|
||||||
|
|||||||
@@ -1836,20 +1836,47 @@ 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($bCheckBackgroundTask = false)
|
public final static function EnterMaintenanceMode($oConfig)
|
||||||
{
|
{
|
||||||
@touch(APPROOT.'.maintenance');
|
@touch(APPROOT.'.maintenance');
|
||||||
if ($bCheckBackgroundTask)
|
SetupPage::log("----> Entering maintenance mode");
|
||||||
|
try
|
||||||
{
|
{
|
||||||
|
// Wait for cron to stop
|
||||||
// Assume database is OK but datamodel is not usable
|
if (is_null($oConfig))
|
||||||
$iCount = CMDBSource::QueryToScalar('SELECT COUNT(*) FROM priv_backgroundtask WHERE running=1');
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Use mutex to check if cron is running
|
||||||
|
$oMutex = new iTopMutex(
|
||||||
|
'cron'.$oConfig->Get('db_name').$oConfig->Get('db_subname'),
|
||||||
|
$oConfig->Get('db_host'),
|
||||||
|
$oConfig->Get('db_user'),
|
||||||
|
$oConfig->Get('db_pwd'),
|
||||||
|
$oConfig->Get('db_tls.enabled'),
|
||||||
|
$oConfig->Get('db_tls.ca')
|
||||||
|
);
|
||||||
|
$iCount = 1;
|
||||||
|
while ($oMutex->IsLocked())
|
||||||
|
{
|
||||||
|
SetupPage::log("Waiting for cron to stop ($iCount)");
|
||||||
|
$iCount++;
|
||||||
|
sleep(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception $e)
|
||||||
|
{
|
||||||
|
// Ignore errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static function ExitMaintenanceMode()
|
public final static function ExitMaintenanceMode($bLog = true)
|
||||||
{
|
{
|
||||||
@unlink(APPROOT.'.maintenance');
|
@unlink(APPROOT.'.maintenance');
|
||||||
|
if ($bLog)
|
||||||
|
{
|
||||||
|
SetupPage::log("<---- Exiting maintenance mode");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -566,7 +566,7 @@ try
|
|||||||
{
|
{
|
||||||
// Note: testing this now in case some of the background processes forces the read-only mode for a while
|
// 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)
|
// in that case it is better to exit with the check on reentrance (mutex)
|
||||||
if (!MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE) || file_exists(APPROOT.'.maintenance'))
|
if (!MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE))
|
||||||
{
|
{
|
||||||
$oP->p("A maintenance is ongoing");
|
$oP->p("A maintenance is ongoing");
|
||||||
$oP->Output();
|
$oP->Output();
|
||||||
|
|||||||
Reference in New Issue
Block a user