N°9144 - fix both UI setup wizard and CLI unattended + replace production by ITOP_DEFAULT_ENV

This commit is contained in:
odain
2026-04-03 16:17:44 +02:00
parent d36f68e3b0
commit 82a20c54a9
25 changed files with 58 additions and 78 deletions

View File

@@ -149,9 +149,9 @@ try {
if (is_subclass_of($sClass, 'WizardStep')) {
/** @var WizardStep $oStep */
$oStep = new $sClass($oDummyController, $sState);
$sConfigFile = utils::GetConfigFilePath();
$sConfigFile = utils::GetConfigFilePath(ITOP_DEFAULT_ENV);
if (file_exists($sConfigFile) && !is_writable($sConfigFile) && $oStep->RequiresWritableConfig()) {
$sRelativePath = utils::GetConfigFilePathRelative();
$sRelativePath = utils::GetConfigFilePathRelative(ITOP_DEFAULT_ENV);
$oPage->error("<b>Error:</b> the configuration file '".$sRelativePath."' already exists and cannot be overwritten.");
$oPage->p("The wizard cannot modify the configuration file for you. If you want to upgrade ".ITOP_APPLICATION.", make sure that the file '<b>".$sRelativePath."</b>' can be modified by the web server.");
$oPage->output();

View File

@@ -290,7 +290,7 @@ class MFCompiler
} else {
$oConfig = null;
}
if (($this->sEnvironment == 'production') && !$bIsAlreadyInMaintenanceMode && $bEnterMaintenanceMode) {
if (($this->sEnvironment == ITOP_DEFAULT_ENV) && !$bIsAlreadyInMaintenanceMode && $bEnterMaintenanceMode) {
SetupUtils::EnterMaintenanceMode($oConfig);
}
if ($bUseSymbolicLinks || $bSkipTempDir) {
@@ -313,7 +313,7 @@ class MFCompiler
// Cleanup the temporary directory
SetupUtils::rrmdir($sTempTargetDir);
}
if (($this->sEnvironment == 'production') && !$bIsAlreadyInMaintenanceMode && $bEnterMaintenanceMode) {
if (($this->sEnvironment == ITOP_DEFAULT_ENV) && !$bIsAlreadyInMaintenanceMode && $bEnterMaintenanceMode) {
SetupUtils::ExitMaintenanceMode();
}
throw $e;
@@ -323,7 +323,7 @@ class MFCompiler
// Move the results to the target directory
SetupUtils::movedir($sTempTargetDir, $sFinalTargetDir);
}
if (($this->sEnvironment == 'production') && !$bIsAlreadyInMaintenanceMode && $bEnterMaintenanceMode) {
if (($this->sEnvironment == ITOP_DEFAULT_ENV) && !$bIsAlreadyInMaintenanceMode && $bEnterMaintenanceMode) {
SetupUtils::ExitMaintenanceMode();
}

View File

@@ -41,7 +41,7 @@ class iTopExtensionsMap
* @param bool $bNormailizeOldExtension true to "magically" convert some well-known old extensions (i.e. a set of modules) to the new iTopExtension format
* @return void
*/
public function __construct($sFromEnvironment = 'production', $aExtraDirs = [])
public function __construct($sFromEnvironment = ITOP_DEFAULT_ENV, $aExtraDirs = [])
{
$this->aExtensions = [];
$this->aExtensionsByCode = [];

View File

@@ -92,7 +92,7 @@ class RunTimeEnvironment
* @param string $sEnvironment (e.g. 'test')
* @param bool $bAutoCommit (make the final environment directly, or build a temporary one)
*/
public function __construct($sEnvironment = 'production', $bAutoCommit = true)
public function __construct($sEnvironment = ITOP_DEFAULT_ENV, $bAutoCommit = true)
{
$this->sFinalEnv = $sEnvironment;
if ($bAutoCommit) {
@@ -167,10 +167,10 @@ class RunTimeEnvironment
}
if (! isset($_SESSION)) {
Session::$bAllowCLI = true;
Session::Start();
//used in all UI setups (not unattended)
session_start();
}
Session::Set('itop_env', $this->sBuildEnv);
$_SESSION['itop_env'] = $this->sBuildEnv;
MetaModel::Startup($oConfig, $bModelOnly, $bUseCache, false, $this->sBuildEnv);
self::$bMetamodelStarted = true;
@@ -1024,12 +1024,11 @@ class RunTimeEnvironment
@chmod($sFinalConfig, 0440); // Read-only for owner and group, nothing for others
@rmdir(dirname($sBuildConfig)); // Cleanup the temporary build dir if empty
MetaModel::ResetAllCaches($this->sFinalEnv);
if (! isset($_SESSION)) {
Session::$bAllowCLI = true;
Session::Start();
//used in all UI setups (not unattended)
session_start();
}
Session::Set('itop_env', $this->sFinalEnv);
$_SESSION['itop_env'] = $this->sFinalEnv;
}
}
@@ -1318,7 +1317,7 @@ class RunTimeEnvironment
public function DataToCleanupAudit()
{
$oSetupAudit = new SetupAudit('production', $this->sBuildEnv);
$oSetupAudit = new SetupAudit(ITOP_DEFAULT_ENV, $this->sBuildEnv);
//Make sure the MetaModel is started before analysing for issues
$sConfFile = utils::GetConfigFilePath($this->sBuildEnv);
@@ -1333,7 +1332,7 @@ class RunTimeEnvironment
public function CopySetupFiles(): void
{
$sSourceEnv = 'production';
$sSourceEnv = ITOP_DEFAULT_ENV;
$sDestinationEnv = $this->sBuildEnv;
if ($sDestinationEnv != $sSourceEnv) {
@@ -1347,10 +1346,6 @@ class RunTimeEnvironment
chmod($sFinalConfig, 0770); // In case it exists: RWX for owner and group, nothing for others
}
SetupUtils::copydir(APPCONF.$sSourceEnv, APPCONF.$sDestinationEnv);
if (is_file($sFinalConfig)) {
chmod($sFinalConfig, 0440); // Read-only for owner and group, nothing for others
}
MetaModel::ResetAllCaches($sDestinationEnv);
}
}
@@ -1456,7 +1451,7 @@ class RunTimeEnvironment
SetupUtils::tidydir($sBuildPath);
}
$oExtensionsMap = new iTopExtensionsMap('production', $aDirsToScan);
$oExtensionsMap = new iTopExtensionsMap(ITOP_DEFAULT_ENV, $aDirsToScan);
// Removed modules are stored as static for FindModules()
$oExtensionsMap->DeclareExtensionAsRemoved($aRemovedExtensionCodes);

View File

@@ -67,7 +67,6 @@ class ApplicationInstallSequencer extends StepSequencer
case 'backup':
if (array_key_exists('backup', $this->oParams->Get('optional_steps', []))) {
$aBackupOptions = $this->oParams->Get('optional_steps')['backup'];
// __DB__-%Y-%m-%d
$sDestination = $aBackupOptions['destination'];
@@ -136,7 +135,7 @@ class ApplicationInstallSequencer extends StepSequencer
return $this->GetNextStep('', "Unknown setup step '$sStep'.", 100, '', self::ERROR);
}
} catch (Exception $e) {
$this->ReportException($e);
SetupLog::Exception("$sStep failed", $e);
$aResult = $this->GetNextStep('', '', 100, $e->getMessage(), self::ERROR);
$aResult['error_code'] = $e->getCode();
return $aResult;

View File

@@ -64,20 +64,19 @@ class DataAuditSequencer extends StepSequencer
$sExtensionDir,
$bUseSymbolicLinks
);
if ($this->IsDataAuditRequired()) {
return $this->GetNextStep('setup-audit', 'Checking data consistency with the new data model', 70, $sMessage);
}
return $this->GetNextStep('', 'Completed', 100);
return $this->GetNextStep('setup-audit', 'Checking data consistency with the new data model', 70, $sMessage);
case 'setup-audit':
$this->oRunTimeEnvironment->DataToCleanupAudit();
if ($this->IsDataAuditRequired()) {
$this->oRunTimeEnvironment->DataToCleanupAudit();
}
return $this->GetNextStep('', 'Completed', 100);
default:
return $this->GetNextStep('', "Unknown setup step '$sStep'.", 100, '', self::ERROR);
}
} catch (Exception $e) {
$this->ReportException($e);
SetupLog::Exception("$sStep failed", $e);
$aResult = $this->GetNextStep('', '', 100, $e->getMessage(), self::ERROR);
$aResult['error_code'] = $e->getCode();
return $aResult;

View File

@@ -159,24 +159,6 @@ abstract class StepSequencer
file_put_contents(APPROOT.'log/'.$sFileName.'.xml', $sSafeXml);
}
protected function ReportException(Exception $e)
{
SetupLog::Error('An exception occurred: '.$e->getMessage().' at line '.$e->getLine().' in file '.$e->getFile());
$idx = 0;
// Log the call stack, but not the parameters since they may contain passwords or other sensitive data
SetupLog::Ok('Call stack:');
foreach ($e->getTrace() as $aTrace) {
$sLine = empty($aTrace['line']) ? '' : $aTrace['line'];
$sFile = empty($aTrace['file']) ? '' : $aTrace['file'];
$sClass = empty($aTrace['class']) ? '' : $aTrace['class'];
$sType = empty($aTrace['type']) ? '' : $aTrace['type'];
$sFunction = empty($aTrace['function']) ? '' : $aTrace['function'];
$sVerb = empty($sClass) ? $sFunction : "$sClass{$sType}$sFunction";
SetupLog::Ok("#$idx $sFile($sLine): $sVerb(...)");
$idx++;
}
}
protected function GetConfig()
{
$sTargetEnvironment = $this->oRunTimeEnvironment->GetBuildEnv();

View File

@@ -915,7 +915,7 @@ class SetupUtils
$aResult['found'] = true;
} elseif (file_exists($sDir.'/conf/production/config-itop.php')) {
$sSourceDir = $sDir;
$sSourceEnvironment = 'production';
$sSourceEnvironment = ITOP_DEFAULT_ENV;
$sConfigFile = $sDir.'/conf/production/config-itop.php';
$aResult['found'] = true;
}
@@ -1586,7 +1586,7 @@ JS
}
$oProductionEnv = new RunTimeEnvironment();
$aRemovedExtensionCodes = json_decode($oWizard->GetParameter('removed_extensions'), true) ?? [];
$oExtensionsMap = new iTopExtensionsMap('production', $aDirsToScan);
$oExtensionsMap = new iTopExtensionsMap(ITOP_DEFAULT_ENV, $aDirsToScan);
$oExtensionsMap->DeclareExtensionAsRemoved($aRemovedExtensionCodes);
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, $aDirsToScan, $bAbortOnMissingDependency, $aModulesToLoad);

View File

@@ -31,7 +31,7 @@ class InstallationFileService
* @param bool $bInstallationOptionalChoicesChecked : this option is used only when no extensions are selected (ie empty
* $aSelectedExtensions)
*/
public function __construct(string $sInstallationPath, string $sTargetEnvironment = 'production', array $aSelectedExtensions = [], bool $bInstallationOptionalChoicesChecked = true)
public function __construct(string $sInstallationPath, string $sTargetEnvironment = ITOP_DEFAULT_ENV, array $aSelectedExtensions = [], bool $bInstallationOptionalChoicesChecked = true)
{
$this->sInstallationPath = $sInstallationPath;
$this->aSelectedModules = [];

View File

@@ -56,7 +56,7 @@ $sMode = $oParams->Get('mode');
$sTargetEnvironment = $oParams->Get('target_env', '');
if ($sTargetEnvironment == '') {
$sTargetEnvironment = 'production';
$sTargetEnvironment = ITOP_DEFAULT_ENV;
}
$sXmlSetupBaseName = basename($sParamFile);
@@ -218,7 +218,7 @@ if ($sMode == 'install') {
//use settings from itop conf
$sTargetEnvironment = $oParams->Get('target_env', '');
if ($sTargetEnvironment == '') {
$sTargetEnvironment = 'production';
$sTargetEnvironment = ITOP_DEFAULT_ENV;
}
$sTargetDir = APPROOT.'env-'.$sTargetEnvironment;
}
@@ -271,6 +271,10 @@ $bFoundIssues = false;
$bInstall = utils::ReadParam('install', true, true /* CLI allowed */);
if ($bInstall) {
if (! isset($_SESSION)) {
$_SESSION = [];
}
echo "Starting the unattended installation...\n";
$oWizard = new DataAuditSequencer($oParams);
$bRes = $oWizard->ExecuteAllSteps();

View File

@@ -190,15 +190,16 @@ class WizardController
*/
protected function DisplayStep(WizardStep $oStep)
{
SetupLog::Info("=== Setup screen: ".$oStep->GetTitle().' ('.get_class($oStep).')');
$oPage = new SetupPage($oStep->GetTitle());
if ($oStep->RequiresWritableConfig()) {
$sConfigFile = utils::GetConfigFilePath();
$sConfigFile = utils::GetConfigFilePath(ITOP_DEFAULT_ENV);
if (file_exists($sConfigFile)) {
// The configuration file already exists
if (!is_writable($sConfigFile)) {
SetupUtils::ExitReadOnlyMode(false); // Reset readonly mode in case of problem
SetupUtils::EraseSetupToken();
$sRelativePath = utils::GetConfigFilePathRelative();
$sRelativePath = utils::GetConfigFilePathRelative(ITOP_DEFAULT_ENV);
$oP = new SetupPage('Installation Cannot Continue');
$oP->add("<h2>Fatal error</h2>\n");
$oP->error("<b>Error:</b> the configuration file '".$sRelativePath."' already exists and cannot be overwritten.");

View File

@@ -95,7 +95,7 @@ class WizStepDone extends WizardStep
// Load the data model only, in order to load env-production/core/main.php to get the XML parameters (needed by GetModuleSettings below)
// But main.php may also contain classes (defined without any module), and thus requiring the full data model
// to be loaded to prevent "class not found" errors...
$oProductionEnv = new RunTimeEnvironment('production');
$oProductionEnv = new RunTimeEnvironment(ITOP_DEFAULT_ENV);
$oProductionEnv->InitDataModel($oConfig, true);
$sIframeUrl = $oConfig->GetModuleSetting('itop-hub-connector', 'setup_url', '');

View File

@@ -60,8 +60,8 @@ class WizStepModulesChoice extends WizardStep
$sConfigPath = null;
if (($sPreviousSourceDir !== '') && is_readable($sPreviousSourceDir.'/conf/production/config-itop.php')) {
$sConfigPath = $sPreviousSourceDir.'/conf/production/config-itop.php';
} elseif (is_readable(utils::GetConfigFilePath('production'))) {
$sConfigPath = utils::GetConfigFilePath('production');
} elseif (is_readable(utils::GetConfigFilePath(ITOP_DEFAULT_ENV))) {
$sConfigPath = utils::GetConfigFilePath(ITOP_DEFAULT_ENV);
}
// only called if the config file exists : we are updating a previous installation !