diff --git a/application/startup.inc.php b/application/startup.inc.php index c3c1abdc3..4082d44b7 100644 --- a/application/startup.inc.php +++ b/application/startup.inc.php @@ -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_start(); $sSwitchEnv = utils::ReadParam('switch_env', null); @@ -120,80 +86,3 @@ else } $sConfigFile = APPCONF.$sEnv.'/'.ITOP_CONFIG_FILE; 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("

$sMessage

"); - $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 '
'.$sMessage.'
'; -} - -/** - * 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; -} \ No newline at end of file diff --git a/approot.inc.php b/approot.inc.php index e5cd6d0f2..585ca3ba8 100644 --- a/approot.inc.php +++ b/approot.inc.php @@ -12,4 +12,56 @@ else { $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; +} diff --git a/maintenancemsg.php b/maintenancemsg.php new file mode 100644 index 000000000..82d24cb25 --- /dev/null +++ b/maintenancemsg.php @@ -0,0 +1,74 @@ +p("

$sMessage

"); + $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 '
'.$sMessage.'
'; +} + +/** + * 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); + } +} diff --git a/pages/exec.php b/pages/exec.php index 62e527dda..e44cbd708 100644 --- a/pages/exec.php +++ b/pages/exec.php @@ -26,16 +26,6 @@ require_once(APPROOT.'core/metamodel.class.php'); 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', ''); if ($sModule == '') { diff --git a/setup/applicationinstaller.class.inc.php b/setup/applicationinstaller.class.inc.php index 1e1ef59ef..0a830e6af 100644 --- a/setup/applicationinstaller.class.inc.php +++ b/setup/applicationinstaller.class.inc.php @@ -137,7 +137,21 @@ class ApplicationInstaller 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 * and the next step to perform @@ -151,7 +165,7 @@ class ApplicationInstaller try { $fStart = microtime(true); - SetupUtils::EnterMaintenanceMode(); + SetupUtils::EnterMaintenanceMode($this->GetConfig()); switch ($sStep) { case '': @@ -356,15 +370,11 @@ class ApplicationInstaller 'next-step-label' => "Unknown setup step '$sStep'.", 'percentage-completed' => 100, ); + break; } - SetupUtils::ExitMaintenanceMode(); - $fDuration = round(microtime(true) - $fStart, 2); - SetupPage::log_info("##### STEP {$sStep} duration: {$fDuration}s"); } catch (Exception $e) { - SetupUtils::ExitMaintenanceMode(); - $aResult = array( 'status' => self::ERROR, 'message' => $e->getMessage(), @@ -389,6 +399,12 @@ class ApplicationInstaller $idx++; } } + finally + { + SetupUtils::ExitMaintenanceMode(); + $fDuration = round(microtime(true) - $fStart, 2); + SetupPage::log_info("##### STEP {$sStep} duration: {$fDuration}s"); + } return $aResult; } @@ -946,6 +962,11 @@ class ApplicationInstaller // Ready to go !! require_once(APPROOT.'core/dict.class.inc.php'); MetaModel::ResetCache(); + + // Perform final setup tasks here + // + $aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), APPROOT.$sModulesDir); + $oProductionEnv->CallInstallerHandlers($aAvailableModules, $aSelectedModuleCodes, 'AfterCreateConfig'); } } diff --git a/setup/index.php b/setup/index.php index 186dac86a..afe8e9413 100644 --- a/setup/index.php +++ b/setup/index.php @@ -17,6 +17,7 @@ * 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.'/bootstrap.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'); 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 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 diff --git a/setup/setuputils.class.inc.php b/setup/setuputils.class.inc.php index 23de149b8..10a31acfd 100644 --- a/setup/setuputils.class.inc.php +++ b/setup/setuputils.class.inc.php @@ -1836,20 +1836,47 @@ EOF 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'); - if ($bCheckBackgroundTask) + SetupPage::log("----> Entering maintenance mode"); + try { - - // Assume database is OK but datamodel is not usable - $iCount = CMDBSource::QueryToScalar('SELECT COUNT(*) FROM priv_backgroundtask WHERE running=1'); + // Wait for cron to stop + if (is_null($oConfig)) + { + 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'); + if ($bLog) + { + SetupPage::log("<---- Exiting maintenance mode"); + } } } diff --git a/webservices/cron.php b/webservices/cron.php index 4c872a92d..3a4288202 100644 --- a/webservices/cron.php +++ b/webservices/cron.php @@ -566,7 +566,7 @@ try { // 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) || file_exists(APPROOT.'.maintenance')) + if (!MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE)) { $oP->p("A maintenance is ongoing"); $oP->Output();