mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-24 02:58:43 +02:00
Merge branch 'support/3.0' into support/3.1
# Conflicts: # setup/modulediscovery.class.inc.php # setup/runtimeenv.class.inc.php # setup/unattended-install/unattended-install.php # tests/setup_params/default-params.xml
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
// iTop is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
@@ -25,7 +25,7 @@ require_once(APPROOT.'setup/backup.class.inc.php');
|
|||||||
* The installation process is split into a sequence of unitary steps
|
* The installation process is split into a sequence of unitary steps
|
||||||
* for performance reasons (i.e; timeout, memory usage) and also in order
|
* for performance reasons (i.e; timeout, memory usage) and also in order
|
||||||
* to provide some feedback about the progress of the installation.
|
* to provide some feedback about the progress of the installation.
|
||||||
*
|
*
|
||||||
* This class can be used for a step by step interactive installation
|
* This class can be used for a step by step interactive installation
|
||||||
* while displaying a progress bar, or in an unattended manner
|
* while displaying a progress bar, or in an unattended manner
|
||||||
* (for example from the command line), to run all the steps
|
* (for example from the command line), to run all the steps
|
||||||
@@ -157,7 +157,7 @@ class ApplicationInstaller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(($aRes['status'] != self::ERROR) && ($aRes['next-step'] != ''));
|
while(($aRes['status'] != self::ERROR) && ($aRes['next-step'] != ''));
|
||||||
|
|
||||||
return ($iOverallStatus == self::OK);
|
return ($iOverallStatus == self::OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ class ApplicationInstaller
|
|||||||
|
|
||||||
case 'copy':
|
case 'copy':
|
||||||
$aPreinstall = $this->oParams->Get('preinstall');
|
$aPreinstall = $this->oParams->Get('preinstall');
|
||||||
$aCopies = $aPreinstall['copies'];
|
$aCopies = $aPreinstall['copies'] ?? [];
|
||||||
|
|
||||||
self::DoCopy($aCopies);
|
self::DoCopy($aCopies);
|
||||||
$sReport = "Copying...";
|
$sReport = "Copying...";
|
||||||
@@ -473,7 +473,7 @@ class ApplicationInstaller
|
|||||||
{
|
{
|
||||||
$sSource = $aCopy['source'];
|
$sSource = $aCopy['source'];
|
||||||
$sDestination = APPROOT.$aCopy['destination'];
|
$sDestination = APPROOT.$aCopy['destination'];
|
||||||
|
|
||||||
SetupUtils::builddir($sDestination);
|
SetupUtils::builddir($sDestination);
|
||||||
SetupUtils::tidydir($sDestination);
|
SetupUtils::tidydir($sDestination);
|
||||||
SetupUtils::copydir($sSource, $sDestination);
|
SetupUtils::copydir($sSource, $sDestination);
|
||||||
@@ -598,10 +598,10 @@ class ApplicationInstaller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$oFactory = new ModelFactory($aDirsToScan);
|
$oFactory = new ModelFactory($aDirsToScan);
|
||||||
|
|
||||||
$oDictModule = new MFDictModule('dictionaries', 'iTop Dictionaries', APPROOT.'dictionaries');
|
$oDictModule = new MFDictModule('dictionaries', 'iTop Dictionaries', APPROOT.'dictionaries');
|
||||||
$oFactory->LoadModule($oDictModule);
|
$oFactory->LoadModule($oDictModule);
|
||||||
|
|
||||||
$sDeltaFile = APPROOT.'core/datamodel.core.xml';
|
$sDeltaFile = APPROOT.'core/datamodel.core.xml';
|
||||||
if (file_exists($sDeltaFile))
|
if (file_exists($sDeltaFile))
|
||||||
{
|
{
|
||||||
@@ -614,7 +614,7 @@ class ApplicationInstaller
|
|||||||
$oApplicationModule = new MFCoreModule('application', 'Application Module', $sDeltaFile);
|
$oApplicationModule = new MFCoreModule('application', 'Application Module', $sDeltaFile);
|
||||||
$oFactory->LoadModule($oApplicationModule);
|
$oFactory->LoadModule($oApplicationModule);
|
||||||
}
|
}
|
||||||
|
|
||||||
$aModules = $oFactory->FindModules();
|
$aModules = $oFactory->FindModules();
|
||||||
|
|
||||||
foreach($aModules as $oModule)
|
foreach($aModules as $oModule)
|
||||||
@@ -627,7 +627,7 @@ class ApplicationInstaller
|
|||||||
}
|
}
|
||||||
// Dump the "reference" model, just before loading any actual delta
|
// Dump the "reference" model, just before loading any actual delta
|
||||||
$oFactory->SaveToFile(APPROOT.'data/datamodel-'.$sEnvironment.'.xml');
|
$oFactory->SaveToFile(APPROOT.'data/datamodel-'.$sEnvironment.'.xml');
|
||||||
|
|
||||||
$sDeltaFile = APPROOT.'data/'.$sEnvironment.'.delta.xml';
|
$sDeltaFile = APPROOT.'data/'.$sEnvironment.'.delta.xml';
|
||||||
if (file_exists($sDeltaFile))
|
if (file_exists($sDeltaFile))
|
||||||
{
|
{
|
||||||
@@ -651,12 +651,12 @@ class ApplicationInstaller
|
|||||||
if (file_exists($sFileToPatch))
|
if (file_exists($sFileToPatch))
|
||||||
{
|
{
|
||||||
$sContent = file_get_contents($sFileToPatch);
|
$sContent = file_get_contents($sFileToPatch);
|
||||||
|
|
||||||
$sContent = str_replace("require_once(APPROOT.'modules/itop-welcome-itil/model.itop-welcome-itil.php');", "//\n// The line below is no longer needed in iTop 2.0 -- patched by the setup program\n// require_once(APPROOT.'modules/itop-welcome-itil/model.itop-welcome-itil.php');", $sContent);
|
$sContent = str_replace("require_once(APPROOT.'modules/itop-welcome-itil/model.itop-welcome-itil.php');", "//\n// The line below is no longer needed in iTop 2.0 -- patched by the setup program\n// require_once(APPROOT.'modules/itop-welcome-itil/model.itop-welcome-itil.php');", $sContent);
|
||||||
|
|
||||||
file_put_contents($sFileToPatch, $sContent);
|
file_put_contents($sFileToPatch, $sContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set an "Instance UUID" identifying this machine based on a file located in the data directory
|
// Set an "Instance UUID" identifying this machine based on a file located in the data directory
|
||||||
$sInstanceUUIDFile = APPROOT.'data/instance.txt';
|
$sInstanceUUIDFile = APPROOT.'data/instance.txt';
|
||||||
SetupUtils::builddir(APPROOT.'data');
|
SetupUtils::builddir(APPROOT.'data');
|
||||||
@@ -728,7 +728,7 @@ class ApplicationInstaller
|
|||||||
{
|
{
|
||||||
SetupLog::Info("Renaming '{$sDBPrefix}priv_internalUser' failed (already done in a previous upgrade?)");
|
SetupLog::Info("Renaming '{$sDBPrefix}priv_internalUser' failed (already done in a previous upgrade?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// let's remove the records in priv_change which have no counterpart in priv_changeop
|
// let's remove the records in priv_change which have no counterpart in priv_changeop
|
||||||
SetupLog::Info("Cleanup of '{$sDBPrefix}priv_change' to remove orphan records");
|
SetupLog::Info("Cleanup of '{$sDBPrefix}priv_change' to remove orphan records");
|
||||||
CMDBSource::SelectDB($sDBName);
|
CMDBSource::SelectDB($sDBName);
|
||||||
@@ -737,7 +737,7 @@ class ApplicationInstaller
|
|||||||
$sTotalCount = "SELECT COUNT(*) FROM `{$sDBPrefix}priv_change`";
|
$sTotalCount = "SELECT COUNT(*) FROM `{$sDBPrefix}priv_change`";
|
||||||
$iTotalCount = (int)CMDBSource::QueryToScalar($sTotalCount);
|
$iTotalCount = (int)CMDBSource::QueryToScalar($sTotalCount);
|
||||||
SetupLog::Info("There is a total of $iTotalCount records in {$sDBPrefix}priv_change.");
|
SetupLog::Info("There is a total of $iTotalCount records in {$sDBPrefix}priv_change.");
|
||||||
|
|
||||||
$sOrphanCount = "SELECT COUNT(c.id) FROM `{$sDBPrefix}priv_change` AS c left join `{$sDBPrefix}priv_changeop` AS o ON c.id = o.changeid WHERE o.id IS NULL";
|
$sOrphanCount = "SELECT COUNT(c.id) FROM `{$sDBPrefix}priv_change` AS c left join `{$sDBPrefix}priv_changeop` AS o ON c.id = o.changeid WHERE o.id IS NULL";
|
||||||
$iOrphanCount = (int)CMDBSource::QueryToScalar($sOrphanCount);
|
$iOrphanCount = (int)CMDBSource::QueryToScalar($sOrphanCount);
|
||||||
SetupLog::Info("There are $iOrphanCount useless records in {$sDBPrefix}priv_change (".sprintf('%.2f', ((100.0*$iOrphanCount)/$iTotalCount))."%)");
|
SetupLog::Info("There are $iOrphanCount useless records in {$sDBPrefix}priv_change (".sprintf('%.2f', ((100.0*$iOrphanCount)/$iTotalCount))."%)");
|
||||||
@@ -763,9 +763,9 @@ class ApplicationInstaller
|
|||||||
{
|
{
|
||||||
SetupLog::Info("Cleanup of orphan records in `{$sDBPrefix}priv_change` failed: ".$e->getMessage());
|
SetupLog::Info("Cleanup of orphan records in `{$sDBPrefix}priv_change` failed: ".$e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module specific actions (migrate the data)
|
// Module specific actions (migrate the data)
|
||||||
//
|
//
|
||||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), APPROOT.$sModulesDir);
|
$aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), APPROOT.$sModulesDir);
|
||||||
@@ -773,9 +773,9 @@ class ApplicationInstaller
|
|||||||
|
|
||||||
if(!$oProductionEnv->CreateDatabaseStructure(MetaModel::GetConfig(), $sMode))
|
if(!$oProductionEnv->CreateDatabaseStructure(MetaModel::GetConfig(), $sMode))
|
||||||
{
|
{
|
||||||
throw new Exception("Failed to create/upgrade the database structure for environment '$sTargetEnvironment'");
|
throw new Exception("Failed to create/upgrade the database structure for environment '$sTargetEnvironment'");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a DBProperty with a unique ID to identify this instance of iTop
|
// Set a DBProperty with a unique ID to identify this instance of iTop
|
||||||
$sUUID = DBProperty::GetProperty('database_uuid', '');
|
$sUUID = DBProperty::GetProperty('database_uuid', '');
|
||||||
if ($sUUID === '')
|
if ($sUUID === '')
|
||||||
@@ -783,10 +783,10 @@ class ApplicationInstaller
|
|||||||
$sUUID = utils::CreateUUID('database');
|
$sUUID = utils::CreateUUID('database');
|
||||||
DBProperty::SetProperty('database_uuid', $sUUID, 'Installation/upgrade of '.ITOP_APPLICATION, 'Unique ID of this '.ITOP_APPLICATION.' Database');
|
DBProperty::SetProperty('database_uuid', $sUUID, 'Installation/upgrade of '.ITOP_APPLICATION, 'Unique ID of this '.ITOP_APPLICATION.' Database');
|
||||||
}
|
}
|
||||||
|
|
||||||
// priv_change now has an 'origin' field to distinguish between the various input sources
|
// priv_change now has an 'origin' field to distinguish between the various input sources
|
||||||
// Let's initialize the field with 'interactive' for all records were it's null
|
// Let's initialize the field with 'interactive' for all records were it's null
|
||||||
// Then check if some records should hold a different value, based on a pattern matching in the userinfo field
|
// Then check if some records should hold a different value, based on a pattern matching in the userinfo field
|
||||||
CMDBSource::SelectDB($sDBName);
|
CMDBSource::SelectDB($sDBName);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -795,20 +795,20 @@ class ApplicationInstaller
|
|||||||
if ($iCount > 0)
|
if ($iCount > 0)
|
||||||
{
|
{
|
||||||
SetupLog::Info("Initializing '{$sDBPrefix}priv_change.origin' ($iCount records to update)");
|
SetupLog::Info("Initializing '{$sDBPrefix}priv_change.origin' ($iCount records to update)");
|
||||||
|
|
||||||
// By default all uninitialized values are considered as 'interactive'
|
// By default all uninitialized values are considered as 'interactive'
|
||||||
$sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'interactive' WHERE `origin` IS NULL";
|
$sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'interactive' WHERE `origin` IS NULL";
|
||||||
CMDBSource::Query($sInit);
|
CMDBSource::Query($sInit);
|
||||||
|
|
||||||
// CSV Import was identified by the comment at the end
|
// CSV Import was identified by the comment at the end
|
||||||
$sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'csv-import.php' WHERE `userinfo` LIKE '%Web Service (CSV)'";
|
$sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'csv-import.php' WHERE `userinfo` LIKE '%Web Service (CSV)'";
|
||||||
CMDBSource::Query($sInit);
|
CMDBSource::Query($sInit);
|
||||||
|
|
||||||
// CSV Import was identified by the comment at the end
|
// CSV Import was identified by the comment at the end
|
||||||
$sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'csv-interactive' WHERE `userinfo` LIKE '%(CSV)' AND origin = 'interactive'";
|
$sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'csv-interactive' WHERE `userinfo` LIKE '%(CSV)' AND origin = 'interactive'";
|
||||||
CMDBSource::Query($sInit);
|
CMDBSource::Query($sInit);
|
||||||
|
|
||||||
|
|
||||||
// Syncho data sources were identified by the comment at the end
|
// Syncho data sources were identified by the comment at the end
|
||||||
// Unfortunately the comment is localized, so we have to search for all possible patterns
|
// Unfortunately the comment is localized, so we have to search for all possible patterns
|
||||||
$sCurrentLanguage = Dict::GetUserLanguage();
|
$sCurrentLanguage = Dict::GetUserLanguage();
|
||||||
@@ -822,7 +822,7 @@ class ApplicationInstaller
|
|||||||
Dict::SetUserLanguage($sCurrentLanguage);
|
Dict::SetUserLanguage($sCurrentLanguage);
|
||||||
$sCondition = "`userinfo` LIKE ".implode(" OR `userinfo` LIKE ", array_keys($aSuffixes));
|
$sCondition = "`userinfo` LIKE ".implode(" OR `userinfo` LIKE ", array_keys($aSuffixes));
|
||||||
|
|
||||||
$sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'synchro-data-source' WHERE ($sCondition)";
|
$sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'synchro-data-source' WHERE ($sCondition)";
|
||||||
CMDBSource::Query($sInit);
|
CMDBSource::Query($sInit);
|
||||||
|
|
||||||
SetupLog::Info("Initialization of '{$sDBPrefix}priv_change.origin' completed.");
|
SetupLog::Info("Initialization of '{$sDBPrefix}priv_change.origin' completed.");
|
||||||
@@ -847,7 +847,7 @@ class ApplicationInstaller
|
|||||||
if ($iCount > 0)
|
if ($iCount > 0)
|
||||||
{
|
{
|
||||||
SetupLog::Info("Initializing '{$sDBPrefix}priv_async_task.status' ($iCount records to update)");
|
SetupLog::Info("Initializing '{$sDBPrefix}priv_async_task.status' ($iCount records to update)");
|
||||||
|
|
||||||
$sInit = "UPDATE `{$sDBPrefix}priv_async_task` SET `status` = 'planned' WHERE (`status` IS NULL) AND (`started` IS NULL)";
|
$sInit = "UPDATE `{$sDBPrefix}priv_async_task` SET `status` = 'planned' WHERE (`status` IS NULL) AND (`started` IS NULL)";
|
||||||
CMDBSource::Query($sInit);
|
CMDBSource::Query($sInit);
|
||||||
|
|
||||||
@@ -903,15 +903,15 @@ class ApplicationInstaller
|
|||||||
$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
|
$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
|
||||||
$oProductionEnv->InitDataModel($oConfig, true); // load data model and connect to the database
|
$oProductionEnv->InitDataModel($oConfig, true); // load data model and connect to the database
|
||||||
$oContextTag = new ContextTag(ContextTag::TAG_SETUP);
|
$oContextTag = new ContextTag(ContextTag::TAG_SETUP);
|
||||||
self::$bMetaModelStarted = true; // No need to reload the final MetaModel in case the installer runs synchronously
|
self::$bMetaModelStarted = true; // No need to reload the final MetaModel in case the installer runs synchronously
|
||||||
|
|
||||||
// Perform here additional DB setup... profiles, etc...
|
// Perform here additional DB setup... profiles, etc...
|
||||||
//
|
//
|
||||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), APPROOT.$sModulesDir);
|
$aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), APPROOT.$sModulesDir);
|
||||||
$oProductionEnv->CallInstallerHandlers($aAvailableModules, $aSelectedModules, 'AfterDatabaseCreation');
|
$oProductionEnv->CallInstallerHandlers($aAvailableModules, $aSelectedModules, 'AfterDatabaseCreation');
|
||||||
|
|
||||||
$oProductionEnv->UpdatePredefinedObjects();
|
$oProductionEnv->UpdatePredefinedObjects();
|
||||||
|
|
||||||
if($sMode == 'install')
|
if($sMode == 'install')
|
||||||
{
|
{
|
||||||
if (!self::CreateAdminAccount(MetaModel::GetConfig(), $sAdminUser, $sAdminPwd, $sAdminLanguage))
|
if (!self::CreateAdminAccount(MetaModel::GetConfig(), $sAdminUser, $sAdminPwd, $sAdminLanguage))
|
||||||
@@ -923,20 +923,20 @@ class ApplicationInstaller
|
|||||||
SetupLog::Info("Administrator account '$sAdminUser' created.");
|
SetupLog::Info("Administrator account '$sAdminUser' created.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform final setup tasks here
|
// Perform final setup tasks here
|
||||||
//
|
//
|
||||||
$oProductionEnv->CallInstallerHandlers($aAvailableModules, $aSelectedModules, 'AfterDatabaseSetup');
|
$oProductionEnv->CallInstallerHandlers($aAvailableModules, $aSelectedModules, 'AfterDatabaseSetup');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to create and administrator account for iTop
|
* Helper function to create and administrator account for iTop
|
||||||
* @return boolean true on success, false otherwise
|
* @return boolean true on success, false otherwise
|
||||||
*/
|
*/
|
||||||
protected static function CreateAdminAccount(Config $oConfig, $sAdminUser, $sAdminPwd, $sLanguage)
|
protected static function CreateAdminAccount(Config $oConfig, $sAdminUser, $sAdminPwd, $sLanguage)
|
||||||
{
|
{
|
||||||
SetupLog::Info('CreateAdminAccount');
|
SetupLog::Info('CreateAdminAccount');
|
||||||
|
|
||||||
if (UserRights::CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage))
|
if (UserRights::CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -962,9 +962,9 @@ class ApplicationInstaller
|
|||||||
'user rights' => 'addons/userrights/userrightsprofile.db.class.inc.php',
|
'user rights' => 'addons/userrights/userrightsprofile.db.class.inc.php',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
|
$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
|
||||||
|
|
||||||
//Load the MetaModel if needed (asynchronous mode)
|
//Load the MetaModel if needed (asynchronous mode)
|
||||||
if (!self::$bMetaModelStarted)
|
if (!self::$bMetaModelStarted)
|
||||||
{
|
{
|
||||||
@@ -972,8 +972,8 @@ class ApplicationInstaller
|
|||||||
$oContextTag = new ContextTag(ContextTag::TAG_SETUP);
|
$oContextTag = new ContextTag(ContextTag::TAG_SETUP);
|
||||||
|
|
||||||
self::$bMetaModelStarted = true; // No need to reload the final MetaModel in case the installer runs synchronously
|
self::$bMetaModelStarted = true; // No need to reload the final MetaModel in case the installer runs synchronously
|
||||||
}
|
}
|
||||||
|
|
||||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, APPROOT.$sModulesDir);
|
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, APPROOT.$sModulesDir);
|
||||||
$oProductionEnv->LoadData($aAvailableModules, $aSelectedModules, $bSampleData);
|
$oProductionEnv->LoadData($aAvailableModules, $aSelectedModules, $bSampleData);
|
||||||
|
|
||||||
@@ -1008,7 +1008,7 @@ class ApplicationInstaller
|
|||||||
$bPreserveModuleSettings = false;
|
$bPreserveModuleSettings = false;
|
||||||
if ($sMode == 'upgrade')
|
if ($sMode == 'upgrade')
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$oOldConfig = new Config($sPreviousConfigFile);
|
$oOldConfig = new Config($sPreviousConfigFile);
|
||||||
$oConfig = clone($oOldConfig);
|
$oConfig = clone($oOldConfig);
|
||||||
@@ -1064,7 +1064,7 @@ class ApplicationInstaller
|
|||||||
@chmod($sConfigDir, 0770); // RWX for owner and group, nothing for others
|
@chmod($sConfigDir, 0770); // RWX for owner and group, nothing for others
|
||||||
|
|
||||||
$oConfig->WriteToFile($sConfigFile);
|
$oConfig->WriteToFile($sConfigFile);
|
||||||
|
|
||||||
// try to make the final config file read-only
|
// try to make the final config file read-only
|
||||||
@chmod($sConfigFile, 0440); // Read-only for owner and group, nothing for others
|
@chmod($sConfigFile, 0440); // Read-only for owner and group, nothing for others
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
// iTop is free software; you can redistribute it and/or modify
|
// iTop is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
@@ -100,14 +100,14 @@ class RunTimeEnvironment
|
|||||||
$this->log_info(sprintf('%.3fs - query: %s ', $fDuration, $sQuery));
|
$this->log_info(sprintf('%.3fs - query: %s ', $fDuration, $sQuery));
|
||||||
$this->log_db_query($sQuery);
|
$this->log_db_query($sQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to initialize the ORM and load the data model
|
* Helper function to initialize the ORM and load the data model
|
||||||
* from the given file
|
* from the given file
|
||||||
* @param $oConfig object The configuration (volatile, not necessarily already on disk)
|
* @param $oConfig object The configuration (volatile, not necessarily already on disk)
|
||||||
* @param $bModelOnly boolean Whether or not to allow loading a data model with no corresponding DB
|
* @param $bModelOnly boolean Whether or not to allow loading a data model with no corresponding DB
|
||||||
* @return none
|
* @return none
|
||||||
*/
|
*/
|
||||||
public function InitDataModel($oConfig, $bModelOnly = true, $bUseCache = false)
|
public function InitDataModel($oConfig, $bModelOnly = true, $bUseCache = false)
|
||||||
{
|
{
|
||||||
require_once APPROOT.'/setup/moduleinstallation.class.inc.php';
|
require_once APPROOT.'/setup/moduleinstallation.class.inc.php';
|
||||||
@@ -121,15 +121,15 @@ class RunTimeEnvironment
|
|||||||
{
|
{
|
||||||
$this->log_info("MetaModel::Startup (ModelOnly = $bModelOnly)");
|
$this->log_info("MetaModel::Startup (ModelOnly = $bModelOnly)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$bUseCache)
|
if (!$bUseCache)
|
||||||
{
|
{
|
||||||
// Reset the cache for the first use !
|
// Reset the cache for the first use !
|
||||||
MetaModel::ResetCache(md5(APPROOT).'-'.$this->sTargetEnv);
|
MetaModel::ResetCache(md5(APPROOT).'-'.$this->sTargetEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaModel::Startup($oConfig, $bModelOnly, $bUseCache, false /* $bTraceSourceFiles */, $this->sTargetEnv);
|
MetaModel::Startup($oConfig, $bModelOnly, $bUseCache, false /* $bTraceSourceFiles */, $this->sTargetEnv);
|
||||||
|
|
||||||
if ($this->oExtensionsMap === null)
|
if ($this->oExtensionsMap === null)
|
||||||
{
|
{
|
||||||
$this->oExtensionsMap = new iTopExtensionsMap($this->sTargetEnv);
|
$this->oExtensionsMap = new iTopExtensionsMap($this->sTargetEnv);
|
||||||
@@ -139,7 +139,7 @@ class RunTimeEnvironment
|
|||||||
/**
|
/**
|
||||||
* Analyzes the current installation and the possibilities
|
* Analyzes the current installation and the possibilities
|
||||||
*
|
*
|
||||||
* @param Config $oConfig Defines the target environment (DB)
|
* @param null|Config $oConfig Defines the target environment (DB)
|
||||||
* @param mixed $modulesPath Either a single string or an array of absolute paths
|
* @param mixed $modulesPath Either a single string or an array of absolute paths
|
||||||
* @param bool $bAbortOnMissingDependency ...
|
* @param bool $bAbortOnMissingDependency ...
|
||||||
* @param array $aModulesToLoad List of modules to search for, defaults to all if omitted
|
* @param array $aModulesToLoad List of modules to search for, defaults to all if omitted
|
||||||
@@ -178,7 +178,7 @@ class RunTimeEnvironment
|
|||||||
'name_code' => ITOP_APPLICATION,
|
'name_code' => ITOP_APPLICATION,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$aDirs = is_array($modulesPath) ? $modulesPath : array($modulesPath);
|
$aDirs = is_array($modulesPath) ? $modulesPath : array($modulesPath);
|
||||||
$aModules = ModuleDiscovery::GetAvailableModules($aDirs, $bAbortOnMissingDependency, $aModulesToLoad);
|
$aModules = ModuleDiscovery::GetAvailableModules($aDirs, $bAbortOnMissingDependency, $aModulesToLoad);
|
||||||
foreach($aModules as $sModuleId => $aModuleInfo)
|
foreach($aModules as $sModuleId => $aModuleInfo)
|
||||||
@@ -194,11 +194,11 @@ class RunTimeEnvironment
|
|||||||
//throw new Exception("Missing version for the module: '$sModuleId'");
|
//throw new Exception("Missing version for the module: '$sModuleId'");
|
||||||
$sModuleVersion = '1.0.0';
|
$sModuleVersion = '1.0.0';
|
||||||
}
|
}
|
||||||
|
|
||||||
$sModuleAppVersion = $aModuleInfo['itop_version'];
|
$sModuleAppVersion = $aModuleInfo['itop_version'];
|
||||||
$aModuleInfo['version_db'] = '';
|
$aModuleInfo['version_db'] = '';
|
||||||
$aModuleInfo['version_code'] = $sModuleVersion;
|
$aModuleInfo['version_code'] = $sModuleVersion;
|
||||||
|
|
||||||
if (!in_array($sModuleAppVersion, array('1.0.0', '1.0.1', '1.0.2')))
|
if (!in_array($sModuleAppVersion, array('1.0.0', '1.0.1', '1.0.2')))
|
||||||
{
|
{
|
||||||
// This module is NOT compatible with the current version
|
// This module is NOT compatible with the current version
|
||||||
@@ -223,18 +223,20 @@ class RunTimeEnvironment
|
|||||||
}
|
}
|
||||||
$aRes[$sModuleName] = $aModuleInfo;
|
$aRes[$sModuleName] = $aModuleInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CMDBSource::InitFromConfig($oConfig);
|
$aSelectInstall = array();
|
||||||
$aSelectInstall = CMDBSource::QueryToArray("SELECT * FROM ".$oConfig->Get('db_subname')."priv_module_install");
|
if (! is_null($oConfig)) {
|
||||||
|
CMDBSource::InitFromConfig($oConfig);
|
||||||
|
$aSelectInstall = CMDBSource::QueryToArray("SELECT * FROM ".$oConfig->Get('db_subname')."priv_module_install");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (MySQLException $e)
|
catch (MySQLException $e)
|
||||||
{
|
{
|
||||||
// No database or erroneous information
|
// No database or erroneous information
|
||||||
$aSelectInstall = array();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the list of installed module (get the latest installation)
|
// Build the list of installed module (get the latest installation)
|
||||||
//
|
//
|
||||||
$aInstallByModule = array(); // array of <module> => array ('installed' => timestamp, 'version' => <version>)
|
$aInstallByModule = array(); // array of <module> => array ('installed' => timestamp, 'version' => <version>)
|
||||||
@@ -251,7 +253,7 @@ class RunTimeEnvironment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($aSelectInstall as $aInstall)
|
foreach ($aSelectInstall as $aInstall)
|
||||||
{
|
{
|
||||||
//$aInstall['comment']; // unsused
|
//$aInstall['comment']; // unsused
|
||||||
@@ -265,7 +267,7 @@ class RunTimeEnvironment
|
|||||||
// as being installed
|
// as being installed
|
||||||
$sModuleVersion = '0.0.0';
|
$sModuleVersion = '0.0.0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($aInstall['parent_id'] == 0)
|
if ($aInstall['parent_id'] == 0)
|
||||||
{
|
{
|
||||||
$sModuleName = ROOT_MODULE;
|
$sModuleName = ROOT_MODULE;
|
||||||
@@ -275,7 +277,7 @@ class RunTimeEnvironment
|
|||||||
// Skip all modules belonging to previous installations
|
// Skip all modules belonging to previous installations
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array_key_exists($sModuleName, $aInstallByModule))
|
if (array_key_exists($sModuleName, $aInstallByModule))
|
||||||
{
|
{
|
||||||
if ($iInstalled < $aInstallByModule[$sModuleName]['installed'])
|
if ($iInstalled < $aInstallByModule[$sModuleName]['installed'])
|
||||||
@@ -283,30 +285,30 @@ class RunTimeEnvironment
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($aInstall['parent_id'] == 0)
|
if ($aInstall['parent_id'] == 0)
|
||||||
{
|
{
|
||||||
$aRes[$sModuleName]['version_db'] = $sModuleVersion;
|
$aRes[$sModuleName]['version_db'] = $sModuleVersion;
|
||||||
$aRes[$sModuleName]['name_db'] = $aInstall['name'];
|
$aRes[$sModuleName]['name_db'] = $aInstall['name'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$aInstallByModule[$sModuleName]['installed'] = $iInstalled;
|
$aInstallByModule[$sModuleName]['installed'] = $iInstalled;
|
||||||
$aInstallByModule[$sModuleName]['version'] = $sModuleVersion;
|
$aInstallByModule[$sModuleName]['version'] = $sModuleVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust the list of proposed modules
|
// Adjust the list of proposed modules
|
||||||
//
|
//
|
||||||
foreach ($aInstallByModule as $sModuleName => $aModuleDB)
|
foreach ($aInstallByModule as $sModuleName => $aModuleDB)
|
||||||
{
|
{
|
||||||
if ($sModuleName == ROOT_MODULE) continue; // Skip the main module
|
if ($sModuleName == ROOT_MODULE) continue; // Skip the main module
|
||||||
|
|
||||||
if (!array_key_exists($sModuleName, $aRes))
|
if (!array_key_exists($sModuleName, $aRes))
|
||||||
{
|
{
|
||||||
// A module was installed, it is not proposed in the new build... skip
|
// A module was installed, it is not proposed in the new build... skip
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$aRes[$sModuleName]['version_db'] = $aModuleDB['version'];
|
$aRes[$sModuleName]['version_db'] = $aModuleDB['version'];
|
||||||
|
|
||||||
if ($aRes[$sModuleName]['install']['flag'] == MODULE_ACTION_MANDATORY)
|
if ($aRes[$sModuleName]['install']['flag'] == MODULE_ACTION_MANDATORY)
|
||||||
{
|
{
|
||||||
$aRes[$sModuleName]['uninstall'] = array(
|
$aRes[$sModuleName]['uninstall'] = array(
|
||||||
@@ -322,7 +324,7 @@ class RunTimeEnvironment
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $aRes;
|
return $aRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,9 +338,9 @@ class RunTimeEnvironment
|
|||||||
{
|
{
|
||||||
self::MakeDirSafe(APPCONF);
|
self::MakeDirSafe(APPCONF);
|
||||||
self::MakeDirSafe(APPCONF.$this->sTargetEnv);
|
self::MakeDirSafe(APPCONF.$this->sTargetEnv);
|
||||||
|
|
||||||
$sTargetConfigFile = APPCONF.$this->sTargetEnv.'/'.ITOP_CONFIG_FILE;
|
$sTargetConfigFile = APPCONF.$this->sTargetEnv.'/'.ITOP_CONFIG_FILE;
|
||||||
|
|
||||||
// Write the config file
|
// Write the config file
|
||||||
@chmod($sTargetConfigFile, 0770); // In case it exists: RWX for owner and group, nothing for others
|
@chmod($sTargetConfigFile, 0770); // In case it exists: RWX for owner and group, nothing for others
|
||||||
$oConfig->WriteToFile($sTargetConfigFile);
|
$oConfig->WriteToFile($sTargetConfigFile);
|
||||||
@@ -354,7 +356,7 @@ class RunTimeEnvironment
|
|||||||
// Do nothing, overload this method if needed
|
// Do nothing, overload this method if needed
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decide whether or not the given extension is selected for installation
|
* Decide whether or not the given extension is selected for installation
|
||||||
* @param iTopExtension $oExtension
|
* @param iTopExtension $oExtension
|
||||||
@@ -364,10 +366,10 @@ class RunTimeEnvironment
|
|||||||
{
|
{
|
||||||
return ($oExtension->sSource == iTopExtension::SOURCE_REMOTE);
|
return ($oExtension->sSource == iTopExtension::SOURCE_REMOTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the installed modules (only the installed ones)
|
* Get the installed modules (only the installed ones)
|
||||||
*/
|
*/
|
||||||
protected function GetMFModulesToCompile($sSourceEnv, $sSourceDir)
|
protected function GetMFModulesToCompile($sSourceEnv, $sSourceDir)
|
||||||
{
|
{
|
||||||
$sSourceDirFull = APPROOT.$sSourceDir;
|
$sSourceDirFull = APPROOT.$sSourceDir;
|
||||||
@@ -388,7 +390,7 @@ class RunTimeEnvironment
|
|||||||
|
|
||||||
$aExtraDirs = $this->GetExtraDirsToScan($aDirsToCompile);
|
$aExtraDirs = $this->GetExtraDirsToScan($aDirsToCompile);
|
||||||
$aDirsToCompile = array_merge($aDirsToCompile, $aExtraDirs);
|
$aDirsToCompile = array_merge($aDirsToCompile, $aExtraDirs);
|
||||||
|
|
||||||
$aRet = array();
|
$aRet = array();
|
||||||
|
|
||||||
// Determine the installed modules and extensions
|
// Determine the installed modules and extensions
|
||||||
@@ -396,7 +398,7 @@ class RunTimeEnvironment
|
|||||||
$oSourceConfig = new Config(APPCONF.$sSourceEnv.'/'.ITOP_CONFIG_FILE);
|
$oSourceConfig = new Config(APPCONF.$sSourceEnv.'/'.ITOP_CONFIG_FILE);
|
||||||
$oSourceEnv = new RunTimeEnvironment($sSourceEnv);
|
$oSourceEnv = new RunTimeEnvironment($sSourceEnv);
|
||||||
$aAvailableModules = $oSourceEnv->AnalyzeInstallation($oSourceConfig, $aDirsToCompile);
|
$aAvailableModules = $oSourceEnv->AnalyzeInstallation($oSourceConfig, $aDirsToCompile);
|
||||||
|
|
||||||
// Actually read the modules available for the target environment,
|
// Actually read the modules available for the target environment,
|
||||||
// but get the selection from the source environment and finally
|
// but get the selection from the source environment and finally
|
||||||
// mark as (automatically) chosen alll the "remote" modules present in the
|
// mark as (automatically) chosen alll the "remote" modules present in the
|
||||||
@@ -416,7 +418,7 @@ class RunTimeEnvironment
|
|||||||
//
|
//
|
||||||
$oDictModule = new MFDictModule('dictionaries', 'iTop Dictionaries', APPROOT.'dictionaries');
|
$oDictModule = new MFDictModule('dictionaries', 'iTop Dictionaries', APPROOT.'dictionaries');
|
||||||
$aRet[$oDictModule->GetName()] = $oDictModule;
|
$aRet[$oDictModule->GetName()] = $oDictModule;
|
||||||
|
|
||||||
$oFactory = new ModelFactory($aDirsToCompile);
|
$oFactory = new ModelFactory($aDirsToCompile);
|
||||||
$sDeltaFile = APPROOT.'core/datamodel.core.xml';
|
$sDeltaFile = APPROOT.'core/datamodel.core.xml';
|
||||||
if (file_exists($sDeltaFile))
|
if (file_exists($sDeltaFile))
|
||||||
@@ -430,14 +432,14 @@ class RunTimeEnvironment
|
|||||||
$oApplicationModule = new MFCoreModule('application', 'Application Module', $sDeltaFile);
|
$oApplicationModule = new MFCoreModule('application', 'Application Module', $sDeltaFile);
|
||||||
$aRet[$oApplicationModule->GetName()] = $oApplicationModule;
|
$aRet[$oApplicationModule->GetName()] = $oApplicationModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
$aModules = $oFactory->FindModules();
|
$aModules = $oFactory->FindModules();
|
||||||
foreach($aModules as $oModule)
|
foreach($aModules as $oModule)
|
||||||
{
|
{
|
||||||
$sModule = $oModule->GetName();
|
$sModule = $oModule->GetName();
|
||||||
$sModuleRootDir = $oModule->GetRootDir();
|
$sModuleRootDir = $oModule->GetRootDir();
|
||||||
$bIsExtra = $this->oExtensionsMap->ModuleIsChosenAsPartOfAnExtension($sModule, iTopExtension::SOURCE_REMOTE);
|
$bIsExtra = $this->oExtensionsMap->ModuleIsChosenAsPartOfAnExtension($sModule, iTopExtension::SOURCE_REMOTE);
|
||||||
if (array_key_exists($sModule, $aAvailableModules))
|
if (array_key_exists($sModule, $aAvailableModules))
|
||||||
{
|
{
|
||||||
if (($aAvailableModules[$sModule]['version_db'] != '') || $bIsExtra && !$oModule->IsAutoSelect()) //Extra modules are always unless they are 'AutoSelect'
|
if (($aAvailableModules[$sModule]['version_db'] != '') || $bIsExtra && !$oModule->IsAutoSelect()) //Extra modules are always unless they are 'AutoSelect'
|
||||||
{
|
{
|
||||||
@@ -445,7 +447,7 @@ class RunTimeEnvironment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now process the 'AutoSelect' modules
|
// Now process the 'AutoSelect' modules
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -564,7 +566,7 @@ class RunTimeEnvironment
|
|||||||
{
|
{
|
||||||
$this->log_info("Creating the structure in '".$oConfig->Get('db_name')."'.");
|
$this->log_info("Creating the structure in '".$oConfig->Get('db_name')."'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//MetaModel::CheckDefinitions();
|
//MetaModel::CheckDefinitions();
|
||||||
if ($sMode == 'install')
|
if ($sMode == 'install')
|
||||||
{
|
{
|
||||||
@@ -596,7 +598,7 @@ class RunTimeEnvironment
|
|||||||
|
|
||||||
MetaModel::DBCreate(array($this, 'LogQueryCallback'));
|
MetaModel::DBCreate(array($this, 'LogQueryCallback'));
|
||||||
$this->log_ok("Database structure successfully updated.");
|
$this->log_ok("Database structure successfully updated.");
|
||||||
|
|
||||||
// Check (and update only if it seems needed) the hierarchical keys
|
// Check (and update only if it seems needed) the hierarchical keys
|
||||||
if (MFCompiler::SkipRebuildHKeys()) {
|
if (MFCompiler::SkipRebuildHKeys()) {
|
||||||
$this->log_ok("Hierchical keys are NOT rebuilt due to the presence of the \"data/.setup-rebuild-hkeys-never\" file");
|
$this->log_ok("Hierchical keys are NOT rebuilt due to the presence of the \"data/.setup-rebuild-hkeys-never\" file");
|
||||||
@@ -656,7 +658,7 @@ class RunTimeEnvironment
|
|||||||
if ($aPredefinedObjects != null)
|
if ($aPredefinedObjects != null)
|
||||||
{
|
{
|
||||||
$this->log_info("$sClass::GetPredefinedObjects() returned " . count($aPredefinedObjects) . " elements.");
|
$this->log_info("$sClass::GetPredefinedObjects() returned " . count($aPredefinedObjects) . " elements.");
|
||||||
|
|
||||||
// Create/Delete/Update objects of this class,
|
// Create/Delete/Update objects of this class,
|
||||||
// according to the given constant values
|
// according to the given constant values
|
||||||
//
|
//
|
||||||
@@ -698,7 +700,7 @@ class RunTimeEnvironment
|
|||||||
// Restore the previous access mode
|
// Restore the previous access mode
|
||||||
$oConfig->Set('access_mode', $iPrevAccessMode);
|
$oConfig->Set('access_mode', $iPrevAccessMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function RecordInstallation(Config $oConfig, $sDataModelVersion, $aSelectedModuleCodes, $aSelectedExtensionCodes, $sShortComment = null)
|
public function RecordInstallation(Config $oConfig, $sDataModelVersion, $aSelectedModuleCodes, $aSelectedExtensionCodes, $sShortComment = null)
|
||||||
{
|
{
|
||||||
// Have it work fine even if the DB has been set in read-only mode for the users
|
// Have it work fine even if the DB has been set in read-only mode for the users
|
||||||
@@ -707,7 +709,7 @@ class RunTimeEnvironment
|
|||||||
//$oConfig->Set('access_mode', ACCESS_FULL);
|
//$oConfig->Set('access_mode', ACCESS_FULL);
|
||||||
|
|
||||||
if (CMDBSource::DBName() == '')
|
if (CMDBSource::DBName() == '')
|
||||||
{
|
{
|
||||||
// In case this has not yet been done
|
// In case this has not yet been done
|
||||||
CMDBSource::InitFromConfig($oConfig);
|
CMDBSource::InitFromConfig($oConfig);
|
||||||
}
|
}
|
||||||
@@ -717,7 +719,7 @@ class RunTimeEnvironment
|
|||||||
$sShortComment = 'Done by the setup program';
|
$sShortComment = 'Done by the setup program';
|
||||||
}
|
}
|
||||||
$sMainComment = $sShortComment."\nBuilt on ".ITOP_BUILD_DATE;
|
$sMainComment = $sShortComment."\nBuilt on ".ITOP_BUILD_DATE;
|
||||||
|
|
||||||
// Record datamodel version
|
// Record datamodel version
|
||||||
$aData = array(
|
$aData = array(
|
||||||
'source_dir' => $oConfig->Get('source_dir'),
|
'source_dir' => $oConfig->Get('source_dir'),
|
||||||
@@ -730,7 +732,7 @@ class RunTimeEnvironment
|
|||||||
$oInstallRec->Set('parent_id', 0); // root module
|
$oInstallRec->Set('parent_id', 0); // root module
|
||||||
$oInstallRec->Set('installed', $iInstallationTime);
|
$oInstallRec->Set('installed', $iInstallationTime);
|
||||||
$iMainItopRecord = $oInstallRec->DBInsertNoReload();
|
$iMainItopRecord = $oInstallRec->DBInsertNoReload();
|
||||||
|
|
||||||
// Record main installation
|
// Record main installation
|
||||||
$oInstallRec = new ModuleInstallation();
|
$oInstallRec = new ModuleInstallation();
|
||||||
$oInstallRec->Set('name', ITOP_APPLICATION);
|
$oInstallRec->Set('name', ITOP_APPLICATION);
|
||||||
@@ -793,7 +795,7 @@ class RunTimeEnvironment
|
|||||||
$this->oExtensionsMap->MarkAsChosen($oExtension->sCode);
|
$this->oExtensionsMap->MarkAsChosen($oExtension->sCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($this->oExtensionsMap->GetChoices() as $oExtension)
|
foreach($this->oExtensionsMap->GetChoices() as $oExtension)
|
||||||
{
|
{
|
||||||
$oInstallRec = new ExtensionInstallation();
|
$oInstallRec = new ExtensionInstallation();
|
||||||
@@ -810,7 +812,7 @@ class RunTimeEnvironment
|
|||||||
MetaModel::GetConfig()->Set('access_mode', $iPrevAccessMode);
|
MetaModel::GetConfig()->Set('access_mode', $iPrevAccessMode);
|
||||||
|
|
||||||
// Database is created, installation has been tracked into it
|
// Database is created, installation has been tracked into it
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -846,7 +848,7 @@ class RunTimeEnvironment
|
|||||||
// as being installed
|
// as being installed
|
||||||
$sModuleVersion = '0.0.0';
|
$sModuleVersion = '0.0.0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($aInstall['parent_id'] == 0)
|
if ($aInstall['parent_id'] == 0)
|
||||||
{
|
{
|
||||||
if ($aInstall['name'] == DATAMODEL_MODULE)
|
if ($aInstall['name'] == DATAMODEL_MODULE)
|
||||||
@@ -888,8 +890,8 @@ class RunTimeEnvironment
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrappers for logging into the setup log files
|
* Wrappers for logging into the setup log files
|
||||||
*/
|
*/
|
||||||
protected function log_error($sText)
|
protected function log_error($sText)
|
||||||
{
|
{
|
||||||
SetupLog::Error($sText);
|
SetupLog::Error($sText);
|
||||||
@@ -925,7 +927,7 @@ class RunTimeEnvironment
|
|||||||
fclose($hSetupQueriesFile);
|
fclose($hSetupQueriesFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetCurrentDataModelVersion()
|
public function GetCurrentDataModelVersion()
|
||||||
{
|
{
|
||||||
$oSearch = DBObjectSearch::FromOQL("SELECT ModuleInstallation WHERE name='".DATAMODEL_MODULE."'");
|
$oSearch = DBObjectSearch::FromOQL("SELECT ModuleInstallation WHERE name='".DATAMODEL_MODULE."'");
|
||||||
@@ -1118,7 +1120,7 @@ class RunTimeEnvironment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load data from XML files for the selected modules (structural data and/or sample data)
|
* Load data from XML files for the selected modules (structural data and/or sample data)
|
||||||
* @param array[] $aAvailableModules All available modules and their definition
|
* @param array[] $aAvailableModules All available modules and their definition
|
||||||
@@ -1170,7 +1172,7 @@ class RunTimeEnvironment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate the load of the previously loaded files, in order to initialize
|
// Simulate the load of the previously loaded files, in order to initialize
|
||||||
// the mapping between the identifiers in the XML and the actual identifiers
|
// the mapping between the identifiers in the XML and the actual identifiers
|
||||||
// in the current database
|
// in the current database
|
||||||
@@ -1182,12 +1184,12 @@ class RunTimeEnvironment
|
|||||||
{
|
{
|
||||||
throw(new Exception("File $sFileName does not exist"));
|
throw(new Exception("File $sFileName does not exist"));
|
||||||
}
|
}
|
||||||
|
|
||||||
$oDataLoader->LoadFile($sFileName, true);
|
$oDataLoader->LoadFile($sFileName, true);
|
||||||
$sResult = sprintf("loading of %s done.", basename($sFileName));
|
$sResult = sprintf("loading of %s done.", basename($sFileName));
|
||||||
SetupLog::Info($sResult);
|
SetupLog::Info($sResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($aFiles as $sFileRelativePath)
|
foreach($aFiles as $sFileRelativePath)
|
||||||
{
|
{
|
||||||
$sFileName = APPROOT.$sFileRelativePath;
|
$sFileName = APPROOT.$sFileRelativePath;
|
||||||
@@ -1196,16 +1198,16 @@ class RunTimeEnvironment
|
|||||||
{
|
{
|
||||||
throw(new Exception("File $sFileName does not exist"));
|
throw(new Exception("File $sFileName does not exist"));
|
||||||
}
|
}
|
||||||
|
|
||||||
$oDataLoader->LoadFile($sFileName);
|
$oDataLoader->LoadFile($sFileName);
|
||||||
$sResult = sprintf("loading of %s done.", basename($sFileName));
|
$sResult = sprintf("loading of %s done.", basename($sFileName));
|
||||||
SetupLog::Info($sResult);
|
SetupLog::Info($sResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
$oDataLoader->EndSession();
|
$oDataLoader->EndSession();
|
||||||
SetupLog::Info("ending data load session");
|
SetupLog::Info("ending data load session");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge two arrays of file names, adding the relative path to the files provided in the array to merge
|
* Merge two arrays of file names, adding the relative path to the files provided in the array to merge
|
||||||
* @param string[] $aSourceArray
|
* @param string[] $aSourceArray
|
||||||
@@ -1222,7 +1224,7 @@ class RunTimeEnvironment
|
|||||||
}
|
}
|
||||||
return array_merge($aSourceArray, $aToMerge);
|
return array_merge($aSourceArray, $aToMerge);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the MetaModel for some common pitfall (class name too long, classes requiring too many joins...)
|
* Check the MetaModel for some common pitfall (class name too long, classes requiring too many joins...)
|
||||||
* The check takes about 900 ms for 200 classes
|
* The check takes about 900 ms for 200 classes
|
||||||
@@ -1262,7 +1264,7 @@ class RunTimeEnvironment
|
|||||||
$iCount++;
|
$iCount++;
|
||||||
}
|
}
|
||||||
$fDuration = microtime(true) - $fStart;
|
$fDuration = microtime(true) - $fStart;
|
||||||
|
|
||||||
return sprintf("Checked %d classes in %.1f ms. No error found.\n", $iCount, $fDuration*1000.0);
|
return sprintf("Checked %d classes in %.1f ms. No error found.\n", $iCount, $fDuration*1000.0);
|
||||||
}
|
}
|
||||||
} // End of class
|
} // End of class
|
||||||
|
|||||||
244
setup/unattended-install/InstallationFileService.php
Normal file
244
setup/unattended-install/InstallationFileService.php
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once(APPROOT.'/application/utils.inc.php');
|
||||||
|
require_once(APPROOT.'/setup/setuppage.class.inc.php');
|
||||||
|
require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
|
||||||
|
require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
|
||||||
|
|
||||||
|
class InstallationFileService {
|
||||||
|
private $sTargetEnvironment;
|
||||||
|
private $sInstallationPath;
|
||||||
|
private $aSelectedModules;
|
||||||
|
private $aSelectedExtensions;
|
||||||
|
private $aUnSelectedModules;
|
||||||
|
private $aAutoSelectModules;
|
||||||
|
private $bInstallationOptionalChoicesChecked;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sInstallationPath
|
||||||
|
* @param string $sTargetEnvironment
|
||||||
|
* @param array $aSelectedExtensions
|
||||||
|
* @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) {
|
||||||
|
$this->sInstallationPath = $sInstallationPath;
|
||||||
|
$this->aSelectedModules = [];
|
||||||
|
$this->aUnSelectedModules = [];
|
||||||
|
$this->sTargetEnvironment = $sTargetEnvironment;
|
||||||
|
$this->aSelectedExtensions = $aSelectedExtensions;
|
||||||
|
$this->bInstallationOptionalChoicesChecked = $bInstallationOptionalChoicesChecked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetSelectedModules(): array {
|
||||||
|
return $this->aSelectedModules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetUnSelectedModules(): array {
|
||||||
|
return $this->aUnSelectedModules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function Init(): void {
|
||||||
|
clearstatcache();
|
||||||
|
|
||||||
|
$this->ProcessDefaultModules();
|
||||||
|
$this->ProcessInstallationChoices();
|
||||||
|
$this->ProcessAutoSelectModules();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ProcessInstallationChoices(): void {
|
||||||
|
$oXMLParameters = new XMLParameters($this->sInstallationPath);
|
||||||
|
$aSteps = $oXMLParameters->Get('steps', []);
|
||||||
|
if (! is_array($aSteps)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($aSteps as $aStepInfo) {
|
||||||
|
$aOptions = $aStepInfo["options"] ?? null;
|
||||||
|
if (! is_null($aOptions) && is_array($aOptions)) {
|
||||||
|
foreach ($aOptions as $aChoiceInfo) {
|
||||||
|
$this->ProcessSelectedChoice($aChoiceInfo, $this->bInstallationOptionalChoicesChecked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$aOptions = $aStepInfo["alternatives"] ?? null;
|
||||||
|
if (! is_null($aOptions) && is_array($aOptions)) {
|
||||||
|
foreach ($aOptions as $aChoiceInfo) {
|
||||||
|
$this->ProcessSelectedChoice($aChoiceInfo, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->aSelectedModules as $sModuleId => $sVal){
|
||||||
|
if (array_key_exists($sModuleId, $this->aUnSelectedModules)){
|
||||||
|
unset($this->aUnSelectedModules[$sModuleId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function ProcessUnSelectedChoice($aChoiceInfo) {
|
||||||
|
if (!is_array($aChoiceInfo)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$aCurrentModules = $aChoiceInfo["modules"] ?? [];
|
||||||
|
foreach ($aCurrentModules as $sModuleId){
|
||||||
|
$this->aUnSelectedModules[$sModuleId] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$aAlternatives = $aChoiceInfo["alternatives"] ?? null;
|
||||||
|
if (!is_null($aAlternatives) && is_array($aAlternatives)) {
|
||||||
|
foreach ($aAlternatives as $aSubChoiceInfo) {
|
||||||
|
$this->ProcessUnSelectedChoice($aSubChoiceInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('sub_options', $aChoiceInfo)) {
|
||||||
|
if (array_key_exists('options', $aChoiceInfo['sub_options'])) {
|
||||||
|
$aSubOptions = $aChoiceInfo['sub_options']['options'];
|
||||||
|
if (!is_null($aSubOptions) && is_array($aSubOptions)) {
|
||||||
|
foreach ($aSubOptions as $aSubChoiceInfo) {
|
||||||
|
$this->ProcessUnSelectedChoice($aSubChoiceInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (array_key_exists('alternatives', $aChoiceInfo['sub_options'])) {
|
||||||
|
$aSubAlternatives = $aChoiceInfo['sub_options']['alternatives'];
|
||||||
|
if (!is_null($aSubAlternatives) && is_array($aSubAlternatives)) {
|
||||||
|
foreach ($aSubAlternatives as $aSubChoiceInfo) {
|
||||||
|
$this->ProcessUnSelectedChoice($aSubChoiceInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function ProcessSelectedChoice($aChoiceInfo, bool $bAllChecked) {
|
||||||
|
if (!is_array($aChoiceInfo)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sDefault = $aChoiceInfo["default"] ?? "false";
|
||||||
|
$sMandatory = $aChoiceInfo["mandatory"] ?? "false";
|
||||||
|
|
||||||
|
$aCurrentModules = $aChoiceInfo["modules"] ?? [];
|
||||||
|
if (0 === count($this->aSelectedExtensions)){
|
||||||
|
$bSelected = $bAllChecked || $sDefault === "true" || $sMandatory === "true";
|
||||||
|
} else {
|
||||||
|
$sExtensionCode = $aChoiceInfo["extension_code"] ?? null;
|
||||||
|
$bSelected = $sMandatory === "true" ||
|
||||||
|
(null !== $sExtensionCode && in_array($sExtensionCode, $this->aSelectedExtensions));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($aCurrentModules as $sModuleId){
|
||||||
|
if ($bSelected) {
|
||||||
|
$this->aSelectedModules[$sModuleId] = true;
|
||||||
|
} else {
|
||||||
|
$this->aUnSelectedModules[$sModuleId] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$aAlternatives = $aChoiceInfo["alternatives"] ?? null;
|
||||||
|
if (!is_null($aAlternatives) && is_array($aAlternatives)) {
|
||||||
|
foreach ($aAlternatives as $aSubChoiceInfo) {
|
||||||
|
if ($bSelected) {
|
||||||
|
$this->ProcessSelectedChoice($aSubChoiceInfo, $bAllChecked);
|
||||||
|
} else {
|
||||||
|
$this->ProcessUnSelectedChoice($aSubChoiceInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('sub_options', $aChoiceInfo)) {
|
||||||
|
if (array_key_exists('options', $aChoiceInfo['sub_options'])) {
|
||||||
|
$aSubOptions = $aChoiceInfo['sub_options']['options'];
|
||||||
|
if (!is_null($aSubOptions) && is_array($aSubOptions)) {
|
||||||
|
foreach ($aSubOptions as $aSubChoiceInfo) {
|
||||||
|
if ($bSelected) {
|
||||||
|
$this->ProcessSelectedChoice($aSubChoiceInfo, $bAllChecked);
|
||||||
|
} else {
|
||||||
|
$this->ProcessUnSelectedChoice($aSubChoiceInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (array_key_exists('alternatives', $aChoiceInfo['sub_options'])) {
|
||||||
|
$aSubAlternatives = $aChoiceInfo['sub_options']['alternatives'];
|
||||||
|
if (!is_null($aSubAlternatives) && is_array($aSubAlternatives)) {
|
||||||
|
foreach ($aSubAlternatives as $aSubChoiceInfo) {
|
||||||
|
if ($bSelected) {
|
||||||
|
$this->ProcessSelectedChoice($aSubChoiceInfo, false);
|
||||||
|
} else {
|
||||||
|
$this->ProcessUnSelectedChoice($aSubChoiceInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function GetExtraDirs() : array {
|
||||||
|
$aSearchDirs = [];
|
||||||
|
|
||||||
|
$aDirs = [
|
||||||
|
'/datamodels/1.x',
|
||||||
|
'/datamodels/2.x',
|
||||||
|
'data/' . $this->sTargetEnvironment . '-modules',
|
||||||
|
'extensions',
|
||||||
|
];
|
||||||
|
foreach ($aDirs as $sRelativeDir){
|
||||||
|
$sDirPath = APPROOT.$sRelativeDir;
|
||||||
|
if (is_dir($sDirPath))
|
||||||
|
{
|
||||||
|
$aSearchDirs[] = $sDirPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $aSearchDirs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ProcessDefaultModules() : void {
|
||||||
|
$sProductionModuleDir = APPROOT.'data/' . $this->sTargetEnvironment . '-modules/';
|
||||||
|
|
||||||
|
$oProductionEnv = new RunTimeEnvironment();
|
||||||
|
$aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), $this->GetExtraDirs(), false, null);
|
||||||
|
|
||||||
|
$this->aAutoSelectModules = [];
|
||||||
|
foreach ($aAvailableModules as $sModuleId => $aModule) {
|
||||||
|
if (($sModuleId != ROOT_MODULE)) {
|
||||||
|
if (isset($aModule['auto_select'])) {
|
||||||
|
$this->aAutoSelectModules[$sModuleId] = $aModule;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($aModule['category'] == 'authentication') || (!$aModule['visible'])) {
|
||||||
|
$this->aSelectedModules[$sModuleId] = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bIsExtra = (array_key_exists('root_dir', $aModule) && (strpos($aModule['root_dir'],
|
||||||
|
$sProductionModuleDir) !== false)); // Some modules (root, datamodel) have no 'root_dir'
|
||||||
|
if ($bIsExtra) {
|
||||||
|
// Modules in data/production-modules/ are considered as mandatory and always installed
|
||||||
|
$this->aSelectedModules[$sModuleId] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ProcessAutoSelectModules() : void {
|
||||||
|
foreach($this->aAutoSelectModules as $sModuleId => $aModule)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$bSelected = false;
|
||||||
|
SetupInfo::SetSelectedModules($this->aSelectedModules);
|
||||||
|
eval('$bSelected = ('.$aModule['auto_select'].');');
|
||||||
|
if ($bSelected)
|
||||||
|
{
|
||||||
|
// Modules in data/production-modules/ are considered as mandatory and always installed
|
||||||
|
$this->aSelectedModules[$sModuleId] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,3 +3,23 @@
|
|||||||
This script allows to install and update iTop via CLI.
|
This script allows to install and update iTop via CLI.
|
||||||
|
|
||||||
For more information, see the official Wiki : [Automated installation [iTop Documentation]](https://www.itophub.io/wiki/page?id=latest:advancedtopics:automatic_install)
|
For more information, see the official Wiki : [Automated installation [iTop Documentation]](https://www.itophub.io/wiki/page?id=latest:advancedtopics:automatic_install)
|
||||||
|
|
||||||
|
|
||||||
|
#install-itop.sh
|
||||||
|
You can install your iTop by only using config-itop.php settings and run either
|
||||||
|
|
||||||
|
- a non-ITIL iTop fresh installation (use itil-fresh-install.xml to have ITIL modules instead)
|
||||||
|
```
|
||||||
|
./install-itop.sh ./xml_setup/fresh-install.xml
|
||||||
|
```
|
||||||
|
|
||||||
|
- a non-ITIL iTop upgrade (use itil-upgrade.xml to have ITIL modules instead)
|
||||||
|
```
|
||||||
|
./install-itop.sh ./xml_setup/upgrade.xml
|
||||||
|
```
|
||||||
|
|
||||||
|
- a specific iTop installation by providing both xml setup file
|
||||||
|
in below example file provided is the one generated by iTop during last setup.
|
||||||
|
```
|
||||||
|
./install-itop.sh ../../log/install-2024-04-03.xml
|
||||||
|
```
|
||||||
|
|||||||
50
setup/unattended-install/install-itop.sh
Normal file
50
setup/unattended-install/install-itop.sh
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
CLI_NAME=$(basename $0)
|
||||||
|
DIR=$(dirname $0)
|
||||||
|
ITOP_DIR="$DIR/../.."
|
||||||
|
|
||||||
|
HELP="Syntax: $CLI_NAME XML_SETUP [INSTALLATION_XML]"
|
||||||
|
|
||||||
|
function HELP {
|
||||||
|
echo $HELP
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $# -lt 1 ]
|
||||||
|
then
|
||||||
|
echo "Missing parameters passed."
|
||||||
|
HELP
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -gt 2 ]
|
||||||
|
then
|
||||||
|
echo "Too much parameters passed ($#) : $*."
|
||||||
|
HELP
|
||||||
|
fi
|
||||||
|
|
||||||
|
XML_SETUP=$1
|
||||||
|
if [ ! -f $XML_SETUP ]
|
||||||
|
then
|
||||||
|
echo "XML_SETUP file ($XML_SETUP) not found."
|
||||||
|
HELP
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -eq 2 ]
|
||||||
|
then
|
||||||
|
INSTALLATION_XML=$2
|
||||||
|
if [ ! -f $INSTALLATION_XML ]
|
||||||
|
then
|
||||||
|
echo "INSTALLATION_XML file ($INSTALLATION_XML) not found."
|
||||||
|
HELP
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
INSTALLATION_XML="$ITOP_DIR/datamodels/2.x/installation.xml"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$CLI_NAME: Using XML_SETUP ($XML_SETUP) and INSTALLATION_XML ($INSTALLATION_XML) files during unattended itop installation."
|
||||||
|
|
||||||
|
rm -rf $ITOP_DIR/data/.maintenance;
|
||||||
|
echo php $DIR/unattended-install.php --use_itop_config --installation_xml="$INSTALLATION_XML" --param-file="$XML_SETUP"
|
||||||
|
|
||||||
|
php $DIR/unattended-install.php --use_itop_config --installation_xml="$INSTALLATION_XML" --param-file="$XML_SETUP"
|
||||||
@@ -1,17 +1,29 @@
|
|||||||
<?php
|
<?php
|
||||||
$bBypassMaintenance = true;
|
|
||||||
require_once(dirname(__FILE__, 3) . '/approot.inc.php');
|
|
||||||
require_once(APPROOT.'/application/utils.inc.php');
|
|
||||||
require_once(APPROOT.'sources/Application/WebPage/CLIPage.php');
|
|
||||||
require_once(APPROOT.'/core/config.class.inc.php');
|
|
||||||
require_once(APPROOT.'/core/log.class.inc.php');
|
|
||||||
require_once(APPROOT.'/core/kpi.class.inc.php');
|
|
||||||
require_once(APPROOT.'/core/cmdbsource.class.inc.php');
|
|
||||||
require_once(APPROOT.'/setup/setuppage.class.inc.php');
|
|
||||||
require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
|
|
||||||
require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
|
|
||||||
require_once(APPROOT.'/setup/applicationinstaller.class.inc.php');
|
|
||||||
|
|
||||||
|
require_once(dirname(__FILE__, 3) . '/approot.inc.php');
|
||||||
|
require_once(__DIR__ . '/InstallationFileService.php');
|
||||||
|
|
||||||
|
function PrintUsageAndExit()
|
||||||
|
{
|
||||||
|
echo <<<EOF
|
||||||
|
Usage: php unattended-install.php --param-file=<path_to_response_file> [--installation_xml=<path_to_installation_xml>] [--use_itop_config]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--param-file=<path_to_response_file> Path to the file (XML) to use for the unattended installation. That file (generated by the setup into log directory) must contain the following sections:
|
||||||
|
- target_env: the target environment (production, test, dev)
|
||||||
|
- database: the database settings (server, user, pwd, name, prefix)
|
||||||
|
- selected_modules: the list of modules to install
|
||||||
|
--response_file DEPRECATED: use `--param-file` instead
|
||||||
|
--installation_xml=<path_to_installation_xml> Use an installation.xml file to compute the modules to install depending on the selected extensions listed in the param file
|
||||||
|
--use_itop_config Use the iTop configuration file to get the database settings, otherwise use the database settings from the parameters file
|
||||||
|
|
||||||
|
Advanced options:
|
||||||
|
--check-consistency=1 Check the data model consistency after the installation (default: 0)
|
||||||
|
--clean=1 In case of a first installation, cleanup the environment before proceeding: delete the configuration file, the cache directory, the target directory, the database (default: 0)
|
||||||
|
--install=0 Set to 0 to perform a dry-run (default: 1)
|
||||||
|
EOF;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
/////////////////////////////////////////////////
|
/////////////////////////////////////////////////
|
||||||
if (! utils::IsModeCLI())
|
if (! utils::IsModeCLI())
|
||||||
{
|
{
|
||||||
@@ -19,17 +31,22 @@ if (! utils::IsModeCLI())
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sParamFile = utils::ReadParam('response_file', 'null', true /* CLI allowed */, 'raw_data');
|
if (in_array('--help', $argv)) {
|
||||||
if ($sParamFile === 'null') {
|
PrintUsageAndExit();
|
||||||
echo "No `--response_file` param specified, using default value !\n";
|
|
||||||
$sParamFile = 'default-params.xml';
|
|
||||||
}
|
}
|
||||||
$bCheckConsistency = (utils::ReadParam('check_consistency', '0', true /* CLI allowed */) == '1');
|
|
||||||
|
$sParamFile = utils::ReadParam('param-file', null, true /* CLI allowed */, 'raw_data') ?? utils::ReadParam('response_file', null, true /* CLI allowed */, 'raw_data');
|
||||||
|
if (is_null($sParamFile)) {
|
||||||
|
echo "Missing mandatory argument `--param-file`.\n";
|
||||||
|
PrintUsageAndExit();
|
||||||
|
}
|
||||||
|
$bCheckConsistency = (utils::ReadParam('check-consistency', '0', true /* CLI allowed */) == '1');
|
||||||
|
|
||||||
if (false === file_exists($sParamFile)) {
|
if (false === file_exists($sParamFile)) {
|
||||||
echo "Param file `$sParamFile` doesn't exist ! Exiting...";
|
echo "Param file `$sParamFile` doesn't exist! Exiting...\n";
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$oParams = new XMLParameters($sParamFile);
|
$oParams = new XMLParameters($sParamFile);
|
||||||
|
|
||||||
$sMode = $oParams->Get('mode');
|
$sMode = $oParams->Get('mode');
|
||||||
@@ -40,8 +57,73 @@ if ($sTargetEnvironment == '')
|
|||||||
$sTargetEnvironment = 'production';
|
$sTargetEnvironment = 'production';
|
||||||
}
|
}
|
||||||
|
|
||||||
//unattended run based on db settings coming from response_file (XML file)
|
$sXmlSetupBaseName = basename($sParamFile);
|
||||||
$aDBXmlSettings = $oParams->Get('database', array());
|
$sInstallationXmlPath = utils::ReadParam('installation_xml', null, true /* CLI allowed */, 'raw_data');
|
||||||
|
if (! is_null($sInstallationXmlPath) && is_file($sInstallationXmlPath)) {
|
||||||
|
$sInstallationBaseName = basename($sInstallationXmlPath);
|
||||||
|
|
||||||
|
$aSelectedExtensionsFromXmlSetup = $oParams->Get('selected_extensions', []);
|
||||||
|
if (count($aSelectedExtensionsFromXmlSetup) !== 0) {
|
||||||
|
$sMsg = "Modules to install computed based on $sInstallationBaseName file and installation choices (listed in section `selected_extensions` of $sXmlSetupBaseName file)";
|
||||||
|
echo "$sMsg:\n".implode(',', $aSelectedExtensionsFromXmlSetup)."\n\n";
|
||||||
|
SetupLog::Info($sMsg, null, $aSelectedExtensionsFromXmlSetup);
|
||||||
|
} else {
|
||||||
|
$sMsg = "Modules to install computed based on default installation choices inside $sInstallationBaseName (no choice specified in section `selected_extensions` of $sXmlSetupBaseName file).";
|
||||||
|
echo "$sMsg\n\n";
|
||||||
|
SetupLog::Info($sMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
$oInstallationFileService = new InstallationFileService($sInstallationXmlPath, $sTargetEnvironment, $aSelectedExtensionsFromXmlSetup);
|
||||||
|
$oInstallationFileService->Init();
|
||||||
|
$aComputedModules = $oInstallationFileService->GetSelectedModules();
|
||||||
|
$aSelectedModules = array_keys($aComputedModules);
|
||||||
|
$oParams->Set('selected_modules', $aSelectedModules);
|
||||||
|
|
||||||
|
$sMsg = "Modules to install computed";
|
||||||
|
} else {
|
||||||
|
$aSelectedModules = $oParams->Get('selected_modules', []);
|
||||||
|
$sMsg = "Modules to install listed in $sXmlSetupBaseName (selected_modules section)";
|
||||||
|
}
|
||||||
|
|
||||||
|
sort($aSelectedModules);
|
||||||
|
echo "$sMsg:\n".implode(',', $aSelectedModules)."\n\n";
|
||||||
|
SetupLog::Info($sMsg, null, $aSelectedModules);
|
||||||
|
|
||||||
|
// Configuration file
|
||||||
|
$sConfigFile = APPCONF.$sTargetEnvironment.'/'.ITOP_CONFIG_FILE;
|
||||||
|
$bUseItopConfig = in_array('--use_itop_config', $argv);
|
||||||
|
if ($bUseItopConfig && file_exists($sConfigFile)){
|
||||||
|
//unattended run based on db settings coming from itop configuration
|
||||||
|
copy($sConfigFile, "$sConfigFile.backup");
|
||||||
|
|
||||||
|
$oConfig = new Config($sConfigFile);
|
||||||
|
$aDBXmlSettings = $oParams->Get('database', array());
|
||||||
|
$aDBXmlSettings ['server'] = $oConfig->Get('db_host');
|
||||||
|
$aDBXmlSettings ['user'] = $oConfig->Get('db_user');
|
||||||
|
$aDBXmlSettings ['pwd'] = $oConfig->Get('db_pwd');
|
||||||
|
$aDBXmlSettings ['name'] = $oConfig->Get('db_name');
|
||||||
|
$aDBXmlSettings ['prefix'] = $oConfig->Get('db_subname');
|
||||||
|
$aDBXmlSettings ['db_tls_enabled'] = $oConfig->Get('db_tls.enabled');
|
||||||
|
//cannot be null or infinite loop triggered!
|
||||||
|
$aDBXmlSettings ['db_tls_ca'] = $oConfig->Get('db_tls.ca') ?? "";
|
||||||
|
$oParams->Set('database', $aDBXmlSettings);
|
||||||
|
|
||||||
|
$aFields = [
|
||||||
|
'url' => 'app_root_url',
|
||||||
|
'source_dir' => 'source_dir',
|
||||||
|
'graphviz_path' => 'graphviz_path',
|
||||||
|
];
|
||||||
|
foreach($aFields as $sSetupField => $sConfField){
|
||||||
|
$oParams->Set($sSetupField, $oConfig->Get($sConfField));
|
||||||
|
}
|
||||||
|
|
||||||
|
$oParams->Set('mysql_bindir', $oConfig->GetModuleSetting('itop-backup', 'mysql_bindir', ""));
|
||||||
|
$oParams->Set('language', $oConfig->GetDefaultLanguage());
|
||||||
|
} else {
|
||||||
|
//unattended run based on db settings coming from response_file (XML file)
|
||||||
|
$aDBXmlSettings = $oParams->Get('database', array());
|
||||||
|
}
|
||||||
|
|
||||||
$sDBServer = $aDBXmlSettings['server'];
|
$sDBServer = $aDBXmlSettings['server'];
|
||||||
$sDBUser = $aDBXmlSettings['user'];
|
$sDBUser = $aDBXmlSettings['user'];
|
||||||
$sDBPwd = $aDBXmlSettings['pwd'];
|
$sDBPwd = $aDBXmlSettings['pwd'];
|
||||||
@@ -57,8 +139,6 @@ if ($sMode == 'install')
|
|||||||
{
|
{
|
||||||
echo "Cleanup mode detected.\n";
|
echo "Cleanup mode detected.\n";
|
||||||
|
|
||||||
// Configuration file
|
|
||||||
$sConfigFile = APPCONF.$sTargetEnvironment.'/'.ITOP_CONFIG_FILE;
|
|
||||||
if (file_exists($sConfigFile))
|
if (file_exists($sConfigFile))
|
||||||
{
|
{
|
||||||
echo "Trying to delete the configuration file: '$sConfigFile'.\n";
|
echo "Trying to delete the configuration file: '$sConfigFile'.\n";
|
||||||
@@ -200,7 +280,7 @@ if ($bHasErrors)
|
|||||||
$sLogMsg = "Encountered stopper issues. Aborting...";
|
$sLogMsg = "Encountered stopper issues. Aborting...";
|
||||||
echo "$sLogMsg\n";
|
echo "$sLogMsg\n";
|
||||||
SetupLog::Error($sLogMsg);
|
SetupLog::Error($sLogMsg);
|
||||||
die;
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$bFoundIssues = false;
|
$bFoundIssues = false;
|
||||||
@@ -291,11 +371,18 @@ if (!$bFoundIssues && $bCheckConsistency)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$bFoundIssues)
|
if (! $bFoundIssues)
|
||||||
{
|
{
|
||||||
// last line: used to check the install
|
// last line: used to check the install
|
||||||
// the only way to track issues in case of Fatal error or even parsing error!
|
// the only way to track issues in case of Fatal error or even parsing error!
|
||||||
$sLogMsg = "installed!";
|
$sLogMsg = "installed!";
|
||||||
|
|
||||||
|
if ($bUseItopConfig && is_file("$sConfigFile.backup"))
|
||||||
|
{
|
||||||
|
echo "\nuse config file provided by backup in $sConfigFile.";
|
||||||
|
copy("$sConfigFile.backup", $sConfigFile);
|
||||||
|
}
|
||||||
|
|
||||||
SetupLog::Info($sLogMsg);
|
SetupLog::Info($sLogMsg);
|
||||||
echo "\n$sLogMsg";
|
echo "\n$sLogMsg";
|
||||||
exit(0);
|
exit(0);
|
||||||
@@ -303,5 +390,5 @@ if (!$bFoundIssues)
|
|||||||
|
|
||||||
$sLogMsg = "installation failed!";
|
$sLogMsg = "installation failed!";
|
||||||
SetupLog::Error($sLogMsg);
|
SetupLog::Error($sLogMsg);
|
||||||
echo "\n$sLogMsg";
|
echo "\n$sLogMsg\n";
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|||||||
41
setup/unattended-install/xml_setup/fresh-install.xml
Normal file
41
setup/unattended-install/xml_setup/fresh-install.xml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<installation>
|
||||||
|
<mode>install</mode>
|
||||||
|
<preinstall>
|
||||||
|
</preinstall>
|
||||||
|
<source_dir>datamodels/2.x/</source_dir>
|
||||||
|
<datamodel_version>2.7.0</datamodel_version>
|
||||||
|
<previous_configuration_file>/var/www/html/iTop/conf/production/config-itop.php</previous_configuration_file>
|
||||||
|
<extensions_dir>extensions</extensions_dir>
|
||||||
|
<target_env>production</target_env>
|
||||||
|
<workspace_dir></workspace_dir>
|
||||||
|
<database>
|
||||||
|
<server></server>
|
||||||
|
<user></user>
|
||||||
|
<pwd></pwd>
|
||||||
|
<name></name>
|
||||||
|
<db_tls_enabled></db_tls_enabled>
|
||||||
|
<db_tls_ca></db_tls_ca>
|
||||||
|
<prefix></prefix>
|
||||||
|
</database>
|
||||||
|
<url></url>
|
||||||
|
<graphviz_path>/usr/bin/dot</graphviz_path>
|
||||||
|
<admin_account>
|
||||||
|
<user></user>
|
||||||
|
<pwd></pwd>
|
||||||
|
<language></language>
|
||||||
|
</admin_account>
|
||||||
|
<language></language>
|
||||||
|
<selected_modules type="array">
|
||||||
|
</selected_modules>
|
||||||
|
<selected_extensions type="array">
|
||||||
|
</selected_extensions>
|
||||||
|
<sample_data>1</sample_data>
|
||||||
|
<old_addon></old_addon>
|
||||||
|
<options type="array"/>
|
||||||
|
<mysql_bindir></mysql_bindir>
|
||||||
|
<selected_modules type="array">
|
||||||
|
</selected_modules>
|
||||||
|
<selected_extensions type="array">
|
||||||
|
</selected_extensions>
|
||||||
|
</installation>
|
||||||
53
setup/unattended-install/xml_setup/itil-fresh-install.xml
Normal file
53
setup/unattended-install/xml_setup/itil-fresh-install.xml
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<installation>
|
||||||
|
<mode>install</mode>
|
||||||
|
<preinstall>
|
||||||
|
</preinstall>
|
||||||
|
<source_dir>datamodels/2.x/</source_dir>
|
||||||
|
<datamodel_version>2.7.0</datamodel_version>
|
||||||
|
<previous_configuration_file>/var/www/html/iTop/conf/production/config-itop.php</previous_configuration_file>
|
||||||
|
<extensions_dir>extensions</extensions_dir>
|
||||||
|
<target_env>production</target_env>
|
||||||
|
<workspace_dir></workspace_dir>
|
||||||
|
<database>
|
||||||
|
<server></server>
|
||||||
|
<user></user>
|
||||||
|
<pwd></pwd>
|
||||||
|
<name></name>
|
||||||
|
<db_tls_enabled></db_tls_enabled>
|
||||||
|
<db_tls_ca></db_tls_ca>
|
||||||
|
<prefix></prefix>
|
||||||
|
</database>
|
||||||
|
<url></url>
|
||||||
|
<graphviz_path>/usr/bin/dot</graphviz_path>
|
||||||
|
<admin_account>
|
||||||
|
<user></user>
|
||||||
|
<pwd></pwd>
|
||||||
|
<language></language>
|
||||||
|
</admin_account>
|
||||||
|
<language></language>
|
||||||
|
<selected_modules type="array">
|
||||||
|
</selected_modules>
|
||||||
|
<selected_extensions type="array">
|
||||||
|
</selected_extensions>
|
||||||
|
<sample_data>1</sample_data>
|
||||||
|
<old_addon></old_addon>
|
||||||
|
<options type="array"/>
|
||||||
|
<mysql_bindir></mysql_bindir>
|
||||||
|
<selected_modules type="array">
|
||||||
|
</selected_modules>
|
||||||
|
<selected_extensions type="array">
|
||||||
|
<item>itop-config-mgmt-datacenter</item>
|
||||||
|
<item>itop-config-mgmt-end-user</item>
|
||||||
|
<item>itop-config-mgmt-storage</item>
|
||||||
|
<item>itop-config-mgmt-virtualization</item>
|
||||||
|
<item>itop-service-mgmt-enterprise</item>
|
||||||
|
<item>itop-ticket-mgmt-itil</item>
|
||||||
|
<item>itop-ticket-mgmt-itil-user-request</item>
|
||||||
|
<item>itop-ticket-mgmt-itil-incident</item>
|
||||||
|
<item>itop-ticket-mgmt-itil-enhanced-portal</item>
|
||||||
|
<item>itop-change-mgmt-itil</item>
|
||||||
|
<item>itop-config-mgmt-core</item>
|
||||||
|
<item>itop-kown-error-mgmt</item>
|
||||||
|
</selected_extensions>
|
||||||
|
</installation>
|
||||||
53
setup/unattended-install/xml_setup/itil-upgrade.xml
Normal file
53
setup/unattended-install/xml_setup/itil-upgrade.xml
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<installation>
|
||||||
|
<mode>upgrade</mode>
|
||||||
|
<preinstall>
|
||||||
|
</preinstall>
|
||||||
|
<source_dir>datamodels/2.x/</source_dir>
|
||||||
|
<datamodel_version>2.7.0</datamodel_version>
|
||||||
|
<previous_configuration_file>/var/www/html/iTop/conf/production/config-itop.php</previous_configuration_file>
|
||||||
|
<extensions_dir>extensions</extensions_dir>
|
||||||
|
<target_env>production</target_env>
|
||||||
|
<workspace_dir></workspace_dir>
|
||||||
|
<database>
|
||||||
|
<server></server>
|
||||||
|
<user></user>
|
||||||
|
<pwd></pwd>
|
||||||
|
<name></name>
|
||||||
|
<db_tls_enabled></db_tls_enabled>
|
||||||
|
<db_tls_ca></db_tls_ca>
|
||||||
|
<prefix></prefix>
|
||||||
|
</database>
|
||||||
|
<url></url>
|
||||||
|
<graphviz_path>/usr/bin/dot</graphviz_path>
|
||||||
|
<admin_account>
|
||||||
|
<user></user>
|
||||||
|
<pwd></pwd>
|
||||||
|
<language></language>
|
||||||
|
</admin_account>
|
||||||
|
<language></language>
|
||||||
|
<selected_modules type="array">
|
||||||
|
</selected_modules>
|
||||||
|
<selected_extensions type="array">
|
||||||
|
</selected_extensions>
|
||||||
|
<sample_data>1</sample_data>
|
||||||
|
<old_addon></old_addon>
|
||||||
|
<options type="array"/>
|
||||||
|
<mysql_bindir></mysql_bindir>
|
||||||
|
<selected_modules type="array">
|
||||||
|
</selected_modules>
|
||||||
|
<selected_extensions type="array">
|
||||||
|
<item>itop-config-mgmt-datacenter</item>
|
||||||
|
<item>itop-config-mgmt-end-user</item>
|
||||||
|
<item>itop-config-mgmt-storage</item>
|
||||||
|
<item>itop-config-mgmt-virtualization</item>
|
||||||
|
<item>itop-service-mgmt-enterprise</item>
|
||||||
|
<item>itop-ticket-mgmt-itil</item>
|
||||||
|
<item>itop-ticket-mgmt-itil-user-request</item>
|
||||||
|
<item>itop-ticket-mgmt-itil-incident</item>
|
||||||
|
<item>itop-ticket-mgmt-itil-enhanced-portal</item>
|
||||||
|
<item>itop-change-mgmt-itil</item>
|
||||||
|
<item>itop-config-mgmt-core</item>
|
||||||
|
<item>itop-kown-error-mgmt</item>
|
||||||
|
</selected_extensions>
|
||||||
|
</installation>
|
||||||
41
setup/unattended-install/xml_setup/upgrade.xml
Normal file
41
setup/unattended-install/xml_setup/upgrade.xml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<installation>
|
||||||
|
<mode>upgrade</mode>
|
||||||
|
<preinstall>
|
||||||
|
</preinstall>
|
||||||
|
<source_dir>datamodels/2.x/</source_dir>
|
||||||
|
<datamodel_version>2.7.0</datamodel_version>
|
||||||
|
<previous_configuration_file>/var/www/html/iTop/conf/production/config-itop.php</previous_configuration_file>
|
||||||
|
<extensions_dir>extensions</extensions_dir>
|
||||||
|
<target_env>production</target_env>
|
||||||
|
<workspace_dir></workspace_dir>
|
||||||
|
<database>
|
||||||
|
<server></server>
|
||||||
|
<user></user>
|
||||||
|
<pwd></pwd>
|
||||||
|
<name></name>
|
||||||
|
<db_tls_enabled></db_tls_enabled>
|
||||||
|
<db_tls_ca></db_tls_ca>
|
||||||
|
<prefix></prefix>
|
||||||
|
</database>
|
||||||
|
<url></url>
|
||||||
|
<graphviz_path>/usr/bin/dot</graphviz_path>
|
||||||
|
<admin_account>
|
||||||
|
<user></user>
|
||||||
|
<pwd></pwd>
|
||||||
|
<language></language>
|
||||||
|
</admin_account>
|
||||||
|
<language></language>
|
||||||
|
<selected_modules type="array">
|
||||||
|
</selected_modules>
|
||||||
|
<selected_extensions type="array">
|
||||||
|
</selected_extensions>
|
||||||
|
<sample_data>1</sample_data>
|
||||||
|
<old_addon></old_addon>
|
||||||
|
<options type="array"/>
|
||||||
|
<mysql_bindir></mysql_bindir>
|
||||||
|
<selected_modules type="array">
|
||||||
|
</selected_modules>
|
||||||
|
<selected_extensions type="array">
|
||||||
|
</selected_extensions>
|
||||||
|
</installation>
|
||||||
@@ -5,7 +5,7 @@ php_version=8.2-apache
|
|||||||
db_version=5.7
|
db_version=5.7
|
||||||
|
|
||||||
[itop]
|
[itop]
|
||||||
itop_setup=tests/setup_params/default-params.xml
|
;itop_setup=tests/setup_params/default-params.xml
|
||||||
itop_backup=tests/backups/backup-itop.tar.gz
|
itop_backup=tests/backups/backup-itop.tar.gz
|
||||||
|
|
||||||
[phpunit]
|
[phpunit]
|
||||||
|
|||||||
@@ -0,0 +1,315 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Combodo\iTop\Test\UnitTest\Setup\UnattendedInstall;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class InstallationFileServiceTest extends TestCase {
|
||||||
|
protected function setUp(): void {
|
||||||
|
parent::setUp();
|
||||||
|
require_once(dirname(__FILE__, 6) . '/setup/unattended-install/InstallationFileService.php');
|
||||||
|
$this->sFolderToCleanup = null;
|
||||||
|
\ModuleDiscovery::ResetCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void {
|
||||||
|
parent::tearDown();
|
||||||
|
|
||||||
|
$sModuleId = "itop-problem-mgmt";
|
||||||
|
$this->RecurseMoveDir(APPROOT."data/production-modules/$sModuleId", APPROOT . "datamodels/2.x/$sModuleId");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetDefaultModulesProvider() {
|
||||||
|
return [
|
||||||
|
'all checked' => [ true ],
|
||||||
|
'only defaut + mandatory' => [ false ],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider GetDefaultModulesProvider
|
||||||
|
*/
|
||||||
|
public function testProcessInstallationChoices($bInstallationOptionalChoicesChecked=false) {
|
||||||
|
$sPath = realpath(dirname(__FILE__, 6)."/datamodels/2.x/installation.xml");
|
||||||
|
$this->assertTrue(is_file($sPath));
|
||||||
|
$oInstallationFileService = new \InstallationFileService($sPath, 'production', [], $bInstallationOptionalChoicesChecked);
|
||||||
|
$oInstallationFileService->ProcessInstallationChoices();
|
||||||
|
$aExpectedModules = [
|
||||||
|
"itop-config-mgmt",
|
||||||
|
"itop-attachments",
|
||||||
|
"itop-profiles-itil",
|
||||||
|
"itop-welcome-itil",
|
||||||
|
"itop-tickets",
|
||||||
|
"itop-files-information",
|
||||||
|
"combodo-db-tools",
|
||||||
|
"itop-core-update",
|
||||||
|
"itop-hub-connector",
|
||||||
|
"itop-oauth-client",
|
||||||
|
"itop-datacenter-mgmt",
|
||||||
|
"itop-endusers-devices",
|
||||||
|
"itop-storage-mgmt",
|
||||||
|
"itop-virtualization-mgmt",
|
||||||
|
"itop-service-mgmt",
|
||||||
|
"itop-request-mgmt",
|
||||||
|
"itop-portal",
|
||||||
|
"itop-portal-base",
|
||||||
|
"itop-change-mgmt",
|
||||||
|
];
|
||||||
|
|
||||||
|
$aExpectedUnselectedModules = [
|
||||||
|
'itop-change-mgmt-itil',
|
||||||
|
'itop-incident-mgmt-itil',
|
||||||
|
'itop-request-mgmt-itil',
|
||||||
|
'itop-service-mgmt-provider',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($bInstallationOptionalChoicesChecked){
|
||||||
|
$aExpectedModules []= "itop-problem-mgmt";
|
||||||
|
$aExpectedModules []= "itop-knownerror-mgmt";
|
||||||
|
} else {
|
||||||
|
$aExpectedUnselectedModules []= "itop-problem-mgmt";
|
||||||
|
$aExpectedUnselectedModules []= "itop-knownerror-mgmt";
|
||||||
|
}
|
||||||
|
|
||||||
|
sort($aExpectedModules);
|
||||||
|
$aModules = array_keys($oInstallationFileService->GetSelectedModules());
|
||||||
|
sort($aModules);
|
||||||
|
|
||||||
|
$this->assertEquals($aExpectedModules, $aModules);
|
||||||
|
|
||||||
|
$aUnselectedModules = array_keys($oInstallationFileService->GetUnSelectedModules());
|
||||||
|
sort($aExpectedUnselectedModules);
|
||||||
|
sort($aUnselectedModules);
|
||||||
|
$this->assertEquals($aExpectedUnselectedModules, $aUnselectedModules);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider GetDefaultModulesProvider
|
||||||
|
*/
|
||||||
|
public function testGetAllSelectedModules($bInstallationOptionalChoicesChecked=false) {
|
||||||
|
$sPath = realpath(dirname(__FILE__, 6)."/datamodels/2.x/installation.xml");
|
||||||
|
$oInstallationFileService = new \InstallationFileService($sPath, 'production', [], $bInstallationOptionalChoicesChecked);
|
||||||
|
$oInstallationFileService->Init();
|
||||||
|
|
||||||
|
$aSelectedModules = $oInstallationFileService->GetSelectedModules();
|
||||||
|
$aExpectedInstallationModules = [
|
||||||
|
"itop-config-mgmt",
|
||||||
|
"itop-attachments",
|
||||||
|
"itop-profiles-itil",
|
||||||
|
"itop-welcome-itil",
|
||||||
|
"itop-tickets",
|
||||||
|
"itop-files-information",
|
||||||
|
"combodo-db-tools",
|
||||||
|
"itop-core-update",
|
||||||
|
"itop-hub-connector",
|
||||||
|
"itop-oauth-client",
|
||||||
|
"itop-datacenter-mgmt",
|
||||||
|
"itop-endusers-devices",
|
||||||
|
"itop-storage-mgmt",
|
||||||
|
"itop-virtualization-mgmt",
|
||||||
|
"itop-service-mgmt",
|
||||||
|
"itop-request-mgmt",
|
||||||
|
"itop-portal",
|
||||||
|
"itop-portal-base",
|
||||||
|
"itop-change-mgmt",
|
||||||
|
];
|
||||||
|
if ($bInstallationOptionalChoicesChecked){
|
||||||
|
$aExpectedInstallationModules []= "itop-problem-mgmt";
|
||||||
|
$aExpectedInstallationModules []= "itop-knownerror-mgmt";
|
||||||
|
}
|
||||||
|
|
||||||
|
$aExpectedAuthenticationModules = [
|
||||||
|
'authent-cas',
|
||||||
|
'authent-external',
|
||||||
|
'authent-ldap',
|
||||||
|
'authent-local',
|
||||||
|
];
|
||||||
|
|
||||||
|
$aUnvisibleModules = [
|
||||||
|
'itop-backup',
|
||||||
|
'itop-config',
|
||||||
|
'itop-sla-computation',
|
||||||
|
];
|
||||||
|
|
||||||
|
$aAutoSelectedModules = [
|
||||||
|
'itop-bridge-virtualization-storage',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkModuleList("installation.xml choices", $aExpectedInstallationModules, $aSelectedModules);
|
||||||
|
$this->checkModuleList("authentication category", $aExpectedAuthenticationModules, $aSelectedModules);
|
||||||
|
$this->checkModuleList("unvisible", $aUnvisibleModules, $aSelectedModules);
|
||||||
|
$this->checkModuleList("auto-select", $aAutoSelectedModules, $aSelectedModules);
|
||||||
|
$this->assertEquals([], $aSelectedModules, "there should be no more modules remaining apart from below lists");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function GetSelectedItilExtensions(bool $coreExtensionIncluded, bool $bKnownMgtIncluded) : array {
|
||||||
|
$aExtensions = [
|
||||||
|
'itop-config-mgmt-datacenter',
|
||||||
|
'itop-config-mgmt-end-user',
|
||||||
|
'itop-config-mgmt-storage',
|
||||||
|
'itop-config-mgmt-virtualization',
|
||||||
|
'itop-service-mgmt-enterprise',
|
||||||
|
'itop-ticket-mgmt-itil',
|
||||||
|
'itop-ticket-mgmt-itil-user-request',
|
||||||
|
'itop-ticket-mgmt-itil-incident',
|
||||||
|
'itop-ticket-mgmt-itil-enhanced-portal',
|
||||||
|
'itop-change-mgmt-itil',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($coreExtensionIncluded){
|
||||||
|
$aExtensions[]= 'itop-config-mgmt-core';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($bKnownMgtIncluded){
|
||||||
|
$aExtensions[]= 'itop-kown-error-mgmt';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $aExtensions;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ItilExtensionProvider() {
|
||||||
|
return [
|
||||||
|
'all itil extensions + INCLUDING known-error-mgt' => [
|
||||||
|
'aSelectedExtensions' => $this->GetSelectedItilExtensions(true, true),
|
||||||
|
'bKnownMgtSelected' => true,
|
||||||
|
],
|
||||||
|
'all itil extensions WITHOUT known-error-mgt' => [
|
||||||
|
'aSelectedExtensions' => $this->GetSelectedItilExtensions(true, false),
|
||||||
|
'bKnownMgtSelected' => false,
|
||||||
|
],
|
||||||
|
'all itil extensions WITHOUT core mandatory ones + INCLUDING known-error-mgt' => [
|
||||||
|
'aSelectedExtensions' => $this->GetSelectedItilExtensions(false, true),
|
||||||
|
'bKnownMgtSelected' => true,
|
||||||
|
],
|
||||||
|
'all itil extensions WITHOUT core mandatory ones and WITHOUT known-error-mgt' => [
|
||||||
|
'aSelectedExtensions' => $this->GetSelectedItilExtensions(false, false),
|
||||||
|
'bKnownMgtSelected' => false,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider ItilExtensionProvider
|
||||||
|
*/
|
||||||
|
public function testGetAllSelectedModules_withItilExtensions(array $aSelectedExtensions, bool $bKnownMgtSelected) {
|
||||||
|
$sPath = realpath(dirname(__FILE__, 6)."/datamodels/2.x/installation.xml");
|
||||||
|
$oInstallationFileService = new \InstallationFileService($sPath, 'production', $aSelectedExtensions);
|
||||||
|
$oInstallationFileService->Init();
|
||||||
|
|
||||||
|
$aSelectedModules = $oInstallationFileService->GetSelectedModules();
|
||||||
|
$aExpectedInstallationModules = [
|
||||||
|
"itop-config-mgmt",
|
||||||
|
"itop-attachments",
|
||||||
|
"itop-profiles-itil",
|
||||||
|
"itop-welcome-itil",
|
||||||
|
"itop-tickets",
|
||||||
|
"itop-files-information",
|
||||||
|
"combodo-db-tools",
|
||||||
|
"itop-core-update",
|
||||||
|
"itop-hub-connector",
|
||||||
|
"itop-oauth-client",
|
||||||
|
"itop-datacenter-mgmt",
|
||||||
|
"itop-endusers-devices",
|
||||||
|
"itop-storage-mgmt",
|
||||||
|
"itop-virtualization-mgmt",
|
||||||
|
"itop-service-mgmt",
|
||||||
|
"itop-request-mgmt-itil",
|
||||||
|
"itop-incident-mgmt-itil",
|
||||||
|
"itop-portal",
|
||||||
|
"itop-portal-base",
|
||||||
|
"itop-change-mgmt-itil",
|
||||||
|
"itop-full-itil",
|
||||||
|
];
|
||||||
|
if ($bKnownMgtSelected){
|
||||||
|
$aExpectedInstallationModules []= "itop-knownerror-mgmt";
|
||||||
|
}
|
||||||
|
|
||||||
|
$aExpectedAuthenticationModules = [
|
||||||
|
'authent-cas',
|
||||||
|
'authent-external',
|
||||||
|
'authent-ldap',
|
||||||
|
'authent-local',
|
||||||
|
];
|
||||||
|
|
||||||
|
$aUnvisibleModules = [
|
||||||
|
'itop-backup',
|
||||||
|
'itop-config',
|
||||||
|
'itop-sla-computation',
|
||||||
|
];
|
||||||
|
|
||||||
|
$aAutoSelectedModules = [
|
||||||
|
'itop-bridge-virtualization-storage',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->checkModuleList("installation.xml choices", $aExpectedInstallationModules, $aSelectedModules);
|
||||||
|
$this->checkModuleList("authentication category", $aExpectedAuthenticationModules, $aSelectedModules);
|
||||||
|
$this->checkModuleList("unvisible", $aUnvisibleModules, $aSelectedModules);
|
||||||
|
$this->checkModuleList("auto-select", $aAutoSelectedModules, $aSelectedModules);
|
||||||
|
$this->assertEquals([], $aSelectedModules, "there should be no more modules remaining apart from below lists");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkModuleList(string $sModuleCategory, array $aExpectedModuleList, array &$aSelectedModules) {
|
||||||
|
$aMissingModules = [];
|
||||||
|
|
||||||
|
foreach ($aExpectedModuleList as $sModuleId){
|
||||||
|
if (! array_key_exists($sModuleId, $aSelectedModules)){
|
||||||
|
$aMissingModules[]=$sModuleId;
|
||||||
|
} else {
|
||||||
|
unset($aSelectedModules[$sModuleId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals([], $aMissingModules, "$sModuleCategory modules are missing");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ProductionModulesProvider() {
|
||||||
|
return [
|
||||||
|
'module autoload as located in production-modules' => [ true ],
|
||||||
|
'module not loaded' => [ false ],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider ProductionModulesProvider
|
||||||
|
*/
|
||||||
|
public function testGetAllSelectedModules_ProductionModules(bool $bModuleInProductionModulesFolder) {
|
||||||
|
$sModuleId = "itop-problem-mgmt";
|
||||||
|
if ($bModuleInProductionModulesFolder){
|
||||||
|
if (! is_dir(APPROOT."data/production-modules")){
|
||||||
|
@mkdir(APPROOT."data/production-modules");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->RecurseMoveDir(APPROOT . "datamodels/2.x/$sModuleId", APPROOT."data/production-modules/$sModuleId");
|
||||||
|
}
|
||||||
|
|
||||||
|
$sPath = realpath(dirname(__FILE__, 6)."/datamodels/2.x/installation.xml");
|
||||||
|
$oInstallationFileService = new \InstallationFileService($sPath, 'production', [], false);
|
||||||
|
$oInstallationFileService->Init();
|
||||||
|
|
||||||
|
$aSelectedModules = $oInstallationFileService->GetSelectedModules();
|
||||||
|
$this->assertEquals($bModuleInProductionModulesFolder, array_key_exists($sModuleId, $aSelectedModules));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function RecurseMoveDir($sFromDir, $sToDir) {
|
||||||
|
if (! is_dir($sFromDir)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! is_dir($sToDir)){
|
||||||
|
@mkdir($sToDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (glob("$sFromDir/*") as $sPath){
|
||||||
|
$sToPath = $sToDir.'/'.basename($sPath);
|
||||||
|
if (is_file($sPath)){
|
||||||
|
@rename($sPath, $sToPath);
|
||||||
|
} else {
|
||||||
|
$this->RecurseMoveDir($sPath, $sToPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@rmdir($sFromDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -63,9 +63,12 @@ class UnattendedInstallTest extends ItopDataTestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function testCallUnattendedInstallFromCLI() {
|
public function testCallUnattendedInstallFromCLI() {
|
||||||
$cliPath = realpath(APPROOT."/setup/unattended-install/unattended-install.php");
|
$sCliPath = realpath(APPROOT."/setup/unattended-install/unattended-install.php");
|
||||||
$res = exec("php ".$cliPath);
|
exec(sprintf("%s %s", PHP_BINARY, $sCliPath), $aOutput, $iCode);
|
||||||
|
|
||||||
$this->assertEquals("Param file `default-params.xml` doesn't exist ! Exiting...", $res);
|
$sOutput = implode('\n', $aOutput);
|
||||||
|
var_dump($sOutput);
|
||||||
|
$this->assertStringContainsString("Missing mandatory argument `--param-file`", $sOutput);
|
||||||
|
$this->assertEquals(255, $iCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,82 +1,41 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<installation>
|
<installation>
|
||||||
<!-- On manual installs, this file is generated in setup/install-*.xml -->
|
<!-- On manual installs, this file is generated in setup/install-*.xml -->
|
||||||
<mode>install</mode>
|
<mode>install</mode>
|
||||||
<preinstall>
|
<preinstall>
|
||||||
<copies type="array"/>
|
<copies type="array"/>
|
||||||
</preinstall>
|
</preinstall>
|
||||||
<source_dir>datamodels/2.x/</source_dir>
|
<source_dir>datamodels/2.x/</source_dir>
|
||||||
<datamodel_version>2.5.0</datamodel_version>
|
<datamodel_version>2.5.0</datamodel_version>
|
||||||
<previous_configuration_file>default-config-itop.php</previous_configuration_file>
|
<previous_configuration_file>default-config-itop.php</previous_configuration_file>
|
||||||
<extensions_dir>extensions</extensions_dir>
|
<extensions_dir>extensions</extensions_dir>
|
||||||
<target_env>production</target_env>
|
<target_env>production</target_env>
|
||||||
<workspace_dir></workspace_dir>
|
<workspace_dir></workspace_dir>
|
||||||
<database>
|
<database>
|
||||||
<server></server>
|
<server></server>
|
||||||
<user>jenkins_itop</user>
|
<user>jenkins_itop</user>
|
||||||
<pwd>IKnowYouSeeMeInJenkinsConf</pwd>
|
<pwd>IKnowYouSeeMeInJenkinsConf</pwd>
|
||||||
<name>itop_ci</name>
|
<name>itop_ci</name>
|
||||||
<db_tls_enabled></db_tls_enabled>
|
<db_tls_enabled></db_tls_enabled>
|
||||||
<db_tls_ca></db_tls_ca>
|
<db_tls_ca></db_tls_ca>
|
||||||
<prefix></prefix>
|
<prefix></prefix>
|
||||||
</database>
|
</database>
|
||||||
<url>http://localhost/iTop/</url>
|
<url>http://localhost/iTop/</url>
|
||||||
<graphviz_path>/usr/bin/dot</graphviz_path>
|
<graphviz_path>/usr/bin/dot</graphviz_path>
|
||||||
<admin_account>
|
<admin_account>
|
||||||
<user>admin</user>
|
<user>admin</user>
|
||||||
<pwd>admin</pwd>
|
<pwd>admin</pwd>
|
||||||
<language>EN US</language>
|
<language>EN US</language>
|
||||||
</admin_account>
|
</admin_account>
|
||||||
<language>EN US</language>
|
<language>EN US</language>
|
||||||
<selected_modules type="array">
|
<selected_modules type="array">
|
||||||
<item>authent-cas</item>
|
</selected_modules>
|
||||||
<item>authent-external</item>
|
<selected_extensions type="array">
|
||||||
<item>authent-ldap</item>
|
</selected_extensions>
|
||||||
<item>authent-local</item>
|
<sample_data>1</sample_data>
|
||||||
<item>itop-backup</item>
|
<old_addon></old_addon>
|
||||||
<item>itop-config</item>
|
<options>
|
||||||
<item>itop-files-information</item>
|
<generate_config>1</generate_config>
|
||||||
<item>itop-portal-base</item>
|
</options>
|
||||||
<item>itop-profiles-itil</item>
|
<mysql_bindir></mysql_bindir>
|
||||||
<item>itop-sla-computation</item>
|
|
||||||
<item>itop-welcome-itil</item>
|
|
||||||
<item>itop-structure</item>
|
|
||||||
<item>itop-config-mgmt</item>
|
|
||||||
<item>itop-attachments</item>
|
|
||||||
<item>itop-tickets</item>
|
|
||||||
<item>combodo-db-tools</item>
|
|
||||||
<item>itop-core-update</item>
|
|
||||||
<item>itop-hub-connector</item>
|
|
||||||
<item>itop-datacenter-mgmt</item>
|
|
||||||
<item>itop-endusers-devices</item>
|
|
||||||
<item>itop-storage-mgmt</item>
|
|
||||||
<item>itop-virtualization-mgmt</item>
|
|
||||||
<item>itop-bridge-virtualization-storage</item>
|
|
||||||
<item>itop-service-mgmt</item>
|
|
||||||
<item>itop-bridge-cmdb-ticket</item>
|
|
||||||
<item>itop-bridge-cmdb-services</item>
|
|
||||||
<item>itop-request-mgmt</item>
|
|
||||||
<item>itop-portal</item>
|
|
||||||
<item>itop-change-mgmt</item>
|
|
||||||
<item>itop-knownerror-mgmt</item>
|
|
||||||
<item>itop-faq-light</item>
|
|
||||||
</selected_modules>
|
|
||||||
<selected_extensions type="array">
|
|
||||||
<item>itop-config-mgmt-core</item>
|
|
||||||
<item>itop-config-mgmt-datacenter</item>
|
|
||||||
<item>itop-config-mgmt-end-user</item>
|
|
||||||
<item>itop-config-mgmt-storage</item>
|
|
||||||
<item>itop-config-mgmt-virtualization</item>
|
|
||||||
<item>itop-service-mgmt-enterprise</item>
|
|
||||||
<item>itop-ticket-mgmt-simple-ticket</item>
|
|
||||||
<item>itop-ticket-mgmt-simple-ticket-enhanced-portal</item>
|
|
||||||
<item>itop-change-mgmt-simple</item>
|
|
||||||
<item>itop-kown-error-mgmt</item>
|
|
||||||
</selected_extensions>
|
|
||||||
<sample_data>1</sample_data>
|
|
||||||
<old_addon></old_addon>
|
|
||||||
<options>
|
|
||||||
<generate_config>1</generate_config>
|
|
||||||
</options>
|
|
||||||
<mysql_bindir></mysql_bindir>
|
|
||||||
</installation>
|
</installation>
|
||||||
|
|||||||
Reference in New Issue
Block a user