mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
Fixed setup issues (improved modularity)
SVN:trunk[1982]
This commit is contained in:
@@ -464,7 +464,15 @@ class utils
|
||||
if (self::$oConfig == null)
|
||||
{
|
||||
$sConfigFile = self::GetConfigFilePath();
|
||||
self::$oConfig = new Config($sConfigFile);
|
||||
if (file_exists($sConfigFile))
|
||||
{
|
||||
self::$oConfig = new Config($sConfigFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// When executing the setup, the config file may be still missing
|
||||
self::$oConfig = new Config();
|
||||
}
|
||||
}
|
||||
return self::$oConfig;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
require_once('MyHelpers.class.inc.php');
|
||||
require_once(APPROOT.'core/kpi.class.inc.php');
|
||||
|
||||
class MySQLException extends CoreException
|
||||
{
|
||||
|
||||
@@ -1462,5 +1462,31 @@ class Config
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: for an array of string, change the prefix when found
|
||||
*/
|
||||
protected static function ChangePrefix(&$aStrings, $sSearchPrefix, $sNewPrefix)
|
||||
{
|
||||
foreach ($aStrings as &$sFile)
|
||||
{
|
||||
if (substr($sFile, 0, strlen($sSearchPrefix)) == $sSearchPrefix)
|
||||
{
|
||||
$sFile = $sNewPrefix.substr($sFile, strlen($sSearchPrefix));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick an dirty way to clone a config file into another environment
|
||||
*/
|
||||
public function ChangeModulesPath($sSourceEnv, $sTargetEnv)
|
||||
{
|
||||
$sSearchPrefix = 'env-'.$sSourceEnv.'/';
|
||||
$sNewPrefix = 'env-'.$sTargetEnv.'/';
|
||||
self::ChangePrefix($this->m_aDataModels, $sSearchPrefix, $sNewPrefix);
|
||||
self::ChangePrefix($this->m_aWebServiceCategories, $sSearchPrefix, $sNewPrefix);
|
||||
self::ChangePrefix($this->m_aDictionaries, $sSearchPrefix, $sNewPrefix);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -227,10 +227,11 @@ try
|
||||
$sModuleDir = Utils::ReadParam('modules_dir', '');
|
||||
$oConfig->UpdateFromParams($aParamValues, $sModuleDir);
|
||||
|
||||
InitDataModel($oConfig, true); // load data model only
|
||||
$oProductionEnv = new RunTimeEnvironment();
|
||||
$oProductionEnv->InitDataModel($oConfig, true); // load data model only
|
||||
|
||||
$sMode = Utils::ReadParam('mode', 'install');
|
||||
if(!CreateDatabaseStructure(MetaModel::GetConfig(), $sMode))
|
||||
if(!$oProductionEnv->CreateDatabaseStructure(MetaModel::GetConfig(), $sMode))
|
||||
{
|
||||
throw(new Exception("Failed to create/upgrade the database structure"));
|
||||
}
|
||||
@@ -256,7 +257,8 @@ try
|
||||
$sModuleDir = Utils::ReadParam('modules_dir', '');
|
||||
$oConfig->UpdateFromParams($aParamValues, $sModuleDir);
|
||||
|
||||
InitDataModel($oConfig, false); // load data model and connect to the database
|
||||
$oProductionEnv = new RunTimeEnvironment();
|
||||
$oProductionEnv->InitDataModel($oConfig, false); // load data model and connect to the database
|
||||
|
||||
$sMode = Utils::ReadParam('mode', 'install');
|
||||
$sSelectedModules = Utils::ReadParam('selected_modules', '', false, 'raw_data');
|
||||
@@ -264,7 +266,7 @@ try
|
||||
|
||||
// Perform here additional DB setup... profiles, etc...
|
||||
//
|
||||
$aAvailableModules = AnalyzeInstallation(MetaModel::GetConfig(), $sModuleDir);
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), $sModuleDir);
|
||||
foreach($aAvailableModules as $sModuleId => $aModule)
|
||||
{
|
||||
if (($sModuleId != ROOT_MODULE) && in_array($sModuleId, $aSelectedModules) &&
|
||||
@@ -278,7 +280,7 @@ try
|
||||
}
|
||||
}
|
||||
|
||||
if (!RecordInstallation($oConfig, $aSelectedModules, $sModuleDir))
|
||||
if (!$oProductionEnv->RecordInstallation($oConfig, $aSelectedModules, $sModuleDir))
|
||||
{
|
||||
throw(new Exception("Failed to record the installation information"));
|
||||
}
|
||||
@@ -326,7 +328,8 @@ try
|
||||
$sModuleDir = Utils::ReadParam('modules_dir', '');
|
||||
$oConfig->UpdateFromParams($aParamValues, $sModuleDir);
|
||||
|
||||
InitDataModel($oConfig, false); // load data model and connect to the database
|
||||
$oProductionEnv = new RunTimeEnvironment();
|
||||
$oProductionEnv->InitDataModel($oConfig, false); // load data model and connect to the database
|
||||
|
||||
$oDataLoader = new XMLDataLoader();
|
||||
if ($sSessionStatus == 'start')
|
||||
|
||||
@@ -398,7 +398,15 @@ EOF;
|
||||
$aClassParams['reconc_keys'] = $sReconcKeys;
|
||||
|
||||
$aClassParams['db_table'] = "'".$oProperties->GetChildText('db_table')."'";
|
||||
$aClassParams['db_key_field'] = "'".$oProperties->GetChildText('db_key_field')."'";
|
||||
|
||||
$sKeyField = $oProperties->GetChildText('db_key_field');
|
||||
if ($sKeyField == '')
|
||||
{
|
||||
$sKeyField = 'id';
|
||||
}
|
||||
$aClassParams['db_key_field'] = "'".$sKeyField."'";
|
||||
|
||||
// TODO: faire automatiquement (pas dans le XML !!!)
|
||||
$aClassParams['db_finalclass_field'] = "'".$oProperties->GetChildText('db_final_class_field')."'";
|
||||
|
||||
if (($sDisplayTemplate = $oProperties->GetChildText('display_template')) && (strlen($sDisplayTemplate) > 0))
|
||||
|
||||
@@ -447,7 +447,8 @@ function PopulateDataFilesList(SetupPage $oP, $aParamValues, $oConfig)
|
||||
$sScript .= "{\n";
|
||||
$sScript .= "if (aFilesToLoad.length > 0) return;"; // Populate the list only once...
|
||||
|
||||
$aAvailableModules = AnalyzeInstallation($oConfig, $aParamValues['source_dir']);
|
||||
$oProductionEnv = new RunTimeEnvironment();
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, $aParamValues['source_dir']);
|
||||
|
||||
$sMode = $aParamValues['mode'];
|
||||
$aStructureDataFiles = array();
|
||||
@@ -595,7 +596,8 @@ function WelcomeAndCheckPrerequisites(SetupPage $oP, $aParamValues, $iCurrentSte
|
||||
{
|
||||
$oConfig = new Config($sConfigFile);
|
||||
|
||||
$aVersion = AnalyzeInstallation($oConfig, 'datamodel');
|
||||
$oProductionEnv = new RunTimeEnvironment();
|
||||
$aVersion = $oProductionEnv->AnalyzeInstallation($oConfig, 'datamodel');
|
||||
if (!empty($aVersion[ROOT_MODULE]['version_db']))
|
||||
{
|
||||
$aPreviousParams = array('mode', 'db_server', 'db_user', 'db_pwd','db_name', 'new_db_name', 'db_prefix', 'source_dir', 'target_dir');
|
||||
@@ -826,7 +828,8 @@ function ModulesSelection(SetupPage $oP, $aParamValues, $iCurrentStep, $oConfig)
|
||||
$sRedStar = '<span class="hilite">*</span>';
|
||||
$oP->set_title("iTop modules selection");
|
||||
|
||||
$aAvailableModules = AnalyzeInstallation($oConfig, $aParamValues['source_dir']);
|
||||
$oProductionEnv = new RunTimeEnvironment();
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, $aParamValues['source_dir']);
|
||||
|
||||
$sConfigFile = utils::GetConfigFilePath();
|
||||
// Form goes here
|
||||
@@ -1132,7 +1135,8 @@ function SampleDataSelection(SetupPage $oP, $aParamValues, $iCurrentStep, Config
|
||||
function DisplaySummary(SetupPage $oP, $aParamValues, $iCurrentStep, Config $oConfig)
|
||||
{
|
||||
$sMode = $aParamValues['mode'];
|
||||
$aAvailableModules = AnalyzeInstallation($oConfig, $aParamValues['source_dir']);
|
||||
$oProductionEnv = new RunTimeEnvironment();
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, $aParamValues['source_dir']);
|
||||
|
||||
$aInstall = array();
|
||||
$aUpgrade = array();
|
||||
@@ -1388,7 +1392,8 @@ function SetupFinished(SetupPage $oP, $aParamValues, $iCurrentStep, Config $oCon
|
||||
$oConfig->WriteToFile($sConfigFile);
|
||||
|
||||
// Start the application
|
||||
InitDataModel($oConfig, false, true); // Load model, startup DB and load the cache
|
||||
$oProductionEnv = new RunTimeEnvironment();
|
||||
$oProductionEnv->InitDataModel($oConfig, false, true); // Load model, startup DB and load the cache
|
||||
if ($aParamValues['mode'] == 'install')
|
||||
{
|
||||
if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd))
|
||||
@@ -1421,7 +1426,8 @@ function SetupFinished(SetupPage $oP, $aParamValues, $iCurrentStep, Config $oCon
|
||||
$oP->add("<form id=\"theForm\" method=\"get\" action=\"../index.php\">\n");
|
||||
|
||||
// Check if there are some manual steps required:
|
||||
$aAvailableModules = AnalyzeInstallation($oConfig, $aParamValues['target_dir']);
|
||||
$oProductionEnv = new RunTimeEnvironment();
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, $aParamValues['target_dir']);
|
||||
$aManualSteps = array();
|
||||
$sRootUrl = utils::GetAbsoluteUrlAppRoot();
|
||||
foreach($aParamValues['module'] as $sModuleId)
|
||||
|
||||
@@ -124,6 +124,7 @@ class ModelFactory
|
||||
$this->sRootDir = $sRootDir;
|
||||
$this->oDOMDocument = new MFDocument();
|
||||
$this->oRoot = $this->oDOMDocument->CreateElement('itop_design');
|
||||
$this->oRoot->setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance");
|
||||
$this->oDOMDocument->AppendChild($this->oRoot);
|
||||
$this->oModules = $this->oDOMDocument->CreateElement('loaded_modules');
|
||||
$this->oRoot->AppendChild($this->oModules);
|
||||
@@ -299,12 +300,18 @@ class ModelFactory
|
||||
$oNodeList = $oXPath->query('/itop_design/classes//class');
|
||||
foreach($oNodeList as $oNode)
|
||||
{
|
||||
$oNode->SetAttribute('_created_in', $sModuleName);
|
||||
if ($oNode->getAttribute('_created_in') == '')
|
||||
{
|
||||
$oNode->SetAttribute('_created_in', $sModuleName);
|
||||
}
|
||||
}
|
||||
$oNodeList = $oXPath->query('/itop_design/menus/menu');
|
||||
foreach($oNodeList as $oNode)
|
||||
{
|
||||
$oNode->SetAttribute('_created_in', $sModuleName);
|
||||
if ($oNode->getAttribute('_created_in') == '')
|
||||
{
|
||||
$oNode->SetAttribute('_created_in', $sModuleName);
|
||||
}
|
||||
}
|
||||
|
||||
$oDeltaRoot = $oDocument->childNodes->item(0);
|
||||
@@ -1648,9 +1655,9 @@ class MFDocument extends DOMDocument
|
||||
if (!$oRootNode)
|
||||
{
|
||||
$oRootNode = $this->createElement('itop_design'); // make sure that the document is not empty
|
||||
$oRootNode->setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance");
|
||||
$this->appendChild($oRootNode);
|
||||
}
|
||||
$oRootNode->setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance");
|
||||
return parent::saveXML();
|
||||
}
|
||||
/**
|
||||
|
||||
380
setup/runtimeenv.class.inc.php
Normal file
380
setup/runtimeenv.class.inc.php
Normal file
@@ -0,0 +1,380 @@
|
||||
<?php
|
||||
// Copyright (C) 2010 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
/**
|
||||
* Web page used for displaying the login form
|
||||
*
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*/
|
||||
|
||||
require_once(APPROOT."setup/modulediscovery.class.inc.php");
|
||||
|
||||
define ('MODULE_ACTION_OPTIONAL', 1);
|
||||
define ('MODULE_ACTION_MANDATORY', 2);
|
||||
define ('MODULE_ACTION_IMPOSSIBLE', 3);
|
||||
define ('ROOT_MODULE', '_Root_'); // Convention to store IN MEMORY the name/version of the root module i.e. application
|
||||
|
||||
class RunTimeEnvironment
|
||||
{
|
||||
protected $sTargetEnv;
|
||||
|
||||
public function __construct($sEnvironment = 'production')
|
||||
{
|
||||
$this->sTargetEnv = $sEnvironment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to initialize the ORM and load the data model
|
||||
* from the given file
|
||||
* @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
|
||||
* @return none
|
||||
*/
|
||||
public function InitDataModel($oConfig, $bModelOnly = true, $bUseCache = false)
|
||||
{
|
||||
require_once(APPROOT.'/core/log.class.inc.php');
|
||||
require_once(APPROOT.'/core/kpi.class.inc.php');
|
||||
require_once(APPROOT.'/core/coreexception.class.inc.php');
|
||||
require_once(APPROOT.'/core/dict.class.inc.php');
|
||||
require_once(APPROOT.'/core/attributedef.class.inc.php');
|
||||
require_once(APPROOT.'/core/filterdef.class.inc.php');
|
||||
require_once(APPROOT.'/core/stimulus.class.inc.php');
|
||||
require_once(APPROOT.'/core/MyHelpers.class.inc.php');
|
||||
require_once(APPROOT.'/core/expression.class.inc.php');
|
||||
require_once(APPROOT.'/core/cmdbsource.class.inc.php');
|
||||
require_once(APPROOT.'/core/sqlquery.class.inc.php');
|
||||
require_once(APPROOT.'/core/dbobject.class.php');
|
||||
require_once(APPROOT.'/core/dbobjectsearch.class.php');
|
||||
require_once(APPROOT.'/core/dbobjectset.class.php');
|
||||
require_once(APPROOT.'/application/cmdbabstract.class.inc.php');
|
||||
require_once(APPROOT.'/core/userrights.class.inc.php');
|
||||
require_once(APPROOT.'/setup/moduleinstallation.class.inc.php');
|
||||
|
||||
$sConfigFile = $oConfig->GetLoadedFile();
|
||||
if (strlen($sConfigFile) > 0)
|
||||
{
|
||||
$this->log_info("MetaModel::Startup from $sConfigFile (ModelOnly = $bModelOnly)");
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->log_info("MetaModel::Startup (ModelOnly = $bModelOnly)");
|
||||
}
|
||||
|
||||
if (!$bUseCache)
|
||||
{
|
||||
// Reset the cache for the first use !
|
||||
MetaModel::ResetCache($oConfig);
|
||||
}
|
||||
|
||||
MetaModel::Startup($oConfig, $bModelOnly, $bUseCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes the current installation and the possibilities
|
||||
*
|
||||
* @param $oConfig Config Defines the target environment (DB)
|
||||
* @return hash Array with the following format:
|
||||
* array =>
|
||||
* 'iTop' => array(
|
||||
* 'version_db' => ... (could be empty in case of a fresh install)
|
||||
* 'version_code => ...
|
||||
* )
|
||||
* <module_name> => array(
|
||||
* 'version_db' => ...
|
||||
* 'version_code' => ...
|
||||
* 'install' => array(
|
||||
* 'flag' => SETUP_NEVER | SETUP_OPTIONAL | SETUP_MANDATORY
|
||||
* 'message' => ...
|
||||
* )
|
||||
* 'uninstall' => array(
|
||||
* 'flag' => SETUP_NEVER | SETUP_OPTIONAL | SETUP_MANDATORY
|
||||
* 'message' => ...
|
||||
* )
|
||||
* 'label' => ...
|
||||
* 'dependencies' => array(<module1>, <module2>, ...)
|
||||
* 'visible' => true | false
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function AnalyzeInstallation($oConfig, $sModulesRelativePath)
|
||||
{
|
||||
$aRes = array(
|
||||
ROOT_MODULE => array(
|
||||
'version_db' => '',
|
||||
'name_db' => '',
|
||||
'version_code' => ITOP_VERSION.'.'.ITOP_REVISION,
|
||||
'name_code' => ITOP_APPLICATION,
|
||||
)
|
||||
);
|
||||
|
||||
$aModules = ModuleDiscovery::GetAvailableModules(APPROOT, $sModulesRelativePath);
|
||||
foreach($aModules as $sModuleId => $aModuleInfo)
|
||||
{
|
||||
list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId);
|
||||
|
||||
$sModuleAppVersion = $aModuleInfo['itop_version'];
|
||||
$aModuleInfo['version_db'] = '';
|
||||
$aModuleInfo['version_code'] = $sModuleVersion;
|
||||
|
||||
if (!in_array($sModuleAppVersion, array('1.0.0', '1.0.1', '1.0.2')))
|
||||
{
|
||||
// This module is NOT compatible with the current version
|
||||
$aModuleInfo['install'] = array(
|
||||
'flag' => MODULE_ACTION_IMPOSSIBLE,
|
||||
'message' => 'the module is not compatible with the current version of the application'
|
||||
);
|
||||
}
|
||||
elseif ($aModuleInfo['mandatory'])
|
||||
{
|
||||
$aModuleInfo['install'] = array(
|
||||
'flag' => MODULE_ACTION_MANDATORY,
|
||||
'message' => 'the module is part of the application'
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aModuleInfo['install'] = array(
|
||||
'flag' => MODULE_ACTION_OPTIONAL,
|
||||
'message' => ''
|
||||
);
|
||||
}
|
||||
$aRes[$sModuleName] = $aModuleInfo;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
CMDBSource::Init($oConfig->GetDBHost(), $oConfig->GetDBUser(), $oConfig->GetDBPwd(), $oConfig->GetDBName());
|
||||
$aSelectInstall = CMDBSource::QueryToArray("SELECT * FROM ".$oConfig->GetDBSubname()."priv_module_install");
|
||||
}
|
||||
catch (MySQLException $e)
|
||||
{
|
||||
// No database or eroneous information
|
||||
$aSelectInstall = array();
|
||||
}
|
||||
|
||||
// Build the list of installed module (get the latest installation)
|
||||
//
|
||||
$aInstallByModule = array(); // array of <module> => array ('installed' => timestamp, 'version' => <version>)
|
||||
foreach ($aSelectInstall as $aInstall)
|
||||
{
|
||||
//$aInstall['comment']; // unsused
|
||||
$iInstalled = strtotime($aInstall['installed']);
|
||||
$sModuleName = $aInstall['name'];
|
||||
$sModuleVersion = $aInstall['version'];
|
||||
|
||||
if ($aInstall['parent_id'] == 0)
|
||||
{
|
||||
$sModuleName = ROOT_MODULE;
|
||||
}
|
||||
|
||||
if (array_key_exists($sModuleName, $aInstallByModule))
|
||||
{
|
||||
if ($iInstalled < $aInstallByModule[$sModuleName]['installed'])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($aInstall['parent_id'] == 0)
|
||||
{
|
||||
$aRes[$sModuleName]['version_db'] = $sModuleVersion;
|
||||
$aRes[$sModuleName]['name_db'] = $aInstall['name'];
|
||||
}
|
||||
|
||||
$aInstallByModule[$sModuleName]['installed'] = $iInstalled;
|
||||
$aInstallByModule[$sModuleName]['version'] = $sModuleVersion;
|
||||
}
|
||||
|
||||
// Adjust the list of proposed modules
|
||||
//
|
||||
foreach ($aInstallByModule as $sModuleName => $aModuleDB)
|
||||
{
|
||||
if ($sModuleName == ROOT_MODULE) continue; // Skip the main module
|
||||
|
||||
if (!array_key_exists($sModuleName, $aRes))
|
||||
{
|
||||
// A module was installed, it is not proposed in the new build... skip
|
||||
continue;
|
||||
}
|
||||
$aRes[$sModuleName]['version_db'] = $aModuleDB['version'];
|
||||
|
||||
if ($aRes[$sModuleName]['install']['flag'] == MODULE_ACTION_MANDATORY)
|
||||
{
|
||||
$aRes[$sModuleName]['uninstall'] = array(
|
||||
'flag' => MODULE_ACTION_IMPOSSIBLE,
|
||||
'message' => 'the module is part of the application'
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aRes[$sModuleName]['uninstall'] = array(
|
||||
'flag' => MODULE_ACTION_OPTIONAL,
|
||||
'message' => ''
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $aRes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create the database structure
|
||||
* @return boolean true on success, false otherwise
|
||||
*/
|
||||
public function CreateDatabaseStructure(Config $oConfig, $sMode)
|
||||
{
|
||||
if (strlen($oConfig->GetDBSubname()) > 0)
|
||||
{
|
||||
$this->log_info("Creating the structure in '".$oConfig->GetDBName()."' (table names prefixed by '".$oConfig->GetDBSubname()."').");
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->log_info("Creating the structure in '".$oConfig->GetDBSubname()."'.");
|
||||
}
|
||||
|
||||
//MetaModel::CheckDefinitions();
|
||||
if ($sMode == 'install')
|
||||
{
|
||||
if (!MetaModel::DBExists(/* bMustBeComplete */ false))
|
||||
{
|
||||
MetaModel::DBCreate();
|
||||
$this->log_ok("Database structure successfully created.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen($oConfig->GetDBSubname()) > 0)
|
||||
{
|
||||
throw new Exception("Error: found iTop tables into the database '".$oConfig->GetDBName()."' (prefix: '".$oConfig->GetDBSubname()."'). Please, try selecting another database instance or specify another prefix to prevent conflicting table names.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Error: found iTop tables into the database '".$oConfig->GetDBName()."'. Please, try selecting another database instance or specify a prefix to prevent conflicting table names.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MetaModel::DBExists(/* bMustBeComplete */ false))
|
||||
{
|
||||
MetaModel::DBCreate();
|
||||
$this->log_ok("Database structure successfully updated.");
|
||||
|
||||
// Check (and update only if it seems needed) the hierarchical keys
|
||||
ob_start();
|
||||
MetaModel::CheckHKeys(false /* bDiagnosticsOnly */, true /* bVerbose*/, true /* bForceUpdate */); // Since in 1.2-beta the detection was buggy, let's force the rebuilding of HKeys
|
||||
$sFeedback = ob_get_clean();
|
||||
$this->log_ok("Hierchical keys rebuilt: $sFeedback");
|
||||
|
||||
// Check (and fix) data sync configuration
|
||||
ob_start();
|
||||
MetaModel::CheckDataSources(false /*$bDiagnostics*/, true/*$bVerbose*/);
|
||||
$sFeedback = ob_get_clean();
|
||||
$this->log_ok("Data sources checked: $sFeedback");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen($oConfig->GetDBSubname()) > 0)
|
||||
{
|
||||
throw new Exception("Error: No previous instance of iTop found into the database '".$oConfig->GetDBName()."' (prefix: '".$oConfig->GetDBSubname()."'). Please, try selecting another database instance.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Error: No previous instance of iTop found into the database '".$oConfig->GetDBName()."'. Please, try selecting another database instance.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function RecordInstallation(Config $oConfig, $aSelectedModules, $sModulesRelativePath)
|
||||
{
|
||||
// Record main installation
|
||||
$oInstallRec = new ModuleInstallation();
|
||||
$oInstallRec->Set('name', ITOP_APPLICATION);
|
||||
$oInstallRec->Set('version', ITOP_VERSION.'.'.ITOP_REVISION);
|
||||
$oInstallRec->Set('comment', "Done by the setup program\nBuilt on ".ITOP_BUILD_DATE);
|
||||
$oInstallRec->Set('parent_id', 0); // root module
|
||||
$iMainItopRecord = $oInstallRec->DBInsertNoReload();
|
||||
|
||||
// Record installed modules
|
||||
//
|
||||
$aAvailableModules = $this->AnalyzeInstallation($oConfig, $sModulesRelativePath);
|
||||
foreach($aSelectedModules as $sModuleId)
|
||||
{
|
||||
$aModuleData = $aAvailableModules[$sModuleId];
|
||||
$sName = $sModuleId;
|
||||
$sVersion = $aModuleData['version_code'];
|
||||
$aComments = array();
|
||||
$aComments[] = 'Done by the setup program';
|
||||
if ($aModuleData['mandatory'])
|
||||
{
|
||||
$aComments[] = 'Mandatory';
|
||||
}
|
||||
else
|
||||
{
|
||||
$aComments[] = 'Optional';
|
||||
}
|
||||
if ($aModuleData['visible'])
|
||||
{
|
||||
$aComments[] = 'Visible (during the setup)';
|
||||
}
|
||||
else
|
||||
{
|
||||
$aComments[] = 'Hidden (selected automatically)';
|
||||
}
|
||||
foreach ($aModuleData['dependencies'] as $sDependOn)
|
||||
{
|
||||
$aComments[] = "Depends on module: $sDependOn";
|
||||
}
|
||||
$sComment = implode("\n", $aComments);
|
||||
|
||||
$oInstallRec = new ModuleInstallation();
|
||||
$oInstallRec->Set('name', $sName);
|
||||
$oInstallRec->Set('version', $sVersion);
|
||||
$oInstallRec->Set('comment', $sComment);
|
||||
$oInstallRec->Set('parent_id', $iMainItopRecord);
|
||||
$oInstallRec->DBInsertNoReload();
|
||||
}
|
||||
// Database is created, installation has been tracked into it
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrappers for logging into the setup log files
|
||||
*/
|
||||
protected function log_error($sText)
|
||||
{
|
||||
SetupPage::log_error($sText);
|
||||
}
|
||||
protected function log_warning($sText)
|
||||
{
|
||||
SetupPage::log_warning($sText);
|
||||
}
|
||||
protected function log_info($sText)
|
||||
{
|
||||
SetupPage::log_info($sText);
|
||||
}
|
||||
protected function log_ok($sText)
|
||||
{
|
||||
SetupPage::log_ok($sText);
|
||||
}
|
||||
} // End of class
|
||||
|
||||
|
||||
?>
|
||||
@@ -25,14 +25,10 @@
|
||||
|
||||
require_once(APPROOT."/application/nicewebpage.class.inc.php");
|
||||
require_once(APPROOT."setup/modulediscovery.class.inc.php");
|
||||
require_once(APPROOT."setup/runtimeenv.class.inc.php");
|
||||
|
||||
define('INSTALL_LOG_FILE', APPROOT.'/setup.log');
|
||||
|
||||
define ('MODULE_ACTION_OPTIONAL', 1);
|
||||
define ('MODULE_ACTION_MANDATORY', 2);
|
||||
define ('MODULE_ACTION_IMPOSSIBLE', 3);
|
||||
define ('ROOT_MODULE', '_Root_'); // Convention to store IN MEMORY the name/version of the root module i.e. application
|
||||
|
||||
date_default_timezone_set('Europe/Paris');
|
||||
class SetupPage extends NiceWebPage
|
||||
{
|
||||
@@ -309,322 +305,4 @@ h3.clickable.open {
|
||||
}
|
||||
} // End of class
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to initialize the ORM and load the data model
|
||||
* from the given file
|
||||
* @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
|
||||
* @return none
|
||||
*/
|
||||
function InitDataModel($oConfig, $bModelOnly = true, $bUseCache = false)
|
||||
{
|
||||
require_once(APPROOT.'/core/log.class.inc.php');
|
||||
require_once(APPROOT.'/core/kpi.class.inc.php');
|
||||
require_once(APPROOT.'/core/coreexception.class.inc.php');
|
||||
require_once(APPROOT.'/core/dict.class.inc.php');
|
||||
require_once(APPROOT.'/core/attributedef.class.inc.php');
|
||||
require_once(APPROOT.'/core/filterdef.class.inc.php');
|
||||
require_once(APPROOT.'/core/stimulus.class.inc.php');
|
||||
require_once(APPROOT.'/core/MyHelpers.class.inc.php');
|
||||
require_once(APPROOT.'/core/expression.class.inc.php');
|
||||
require_once(APPROOT.'/core/cmdbsource.class.inc.php');
|
||||
require_once(APPROOT.'/core/sqlquery.class.inc.php');
|
||||
require_once(APPROOT.'/core/dbobject.class.php');
|
||||
require_once(APPROOT.'/core/dbobjectsearch.class.php');
|
||||
require_once(APPROOT.'/core/dbobjectset.class.php');
|
||||
require_once(APPROOT.'/application/cmdbabstract.class.inc.php');
|
||||
require_once(APPROOT.'/core/userrights.class.inc.php');
|
||||
require_once(APPROOT.'/setup/moduleinstallation.class.inc.php');
|
||||
|
||||
$sConfigFile = $oConfig->GetLoadedFile();
|
||||
if (strlen($sConfigFile) > 0)
|
||||
{
|
||||
SetupPage::log_info("MetaModel::Startup from $sConfigFile (ModelOnly = $bModelOnly)");
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupPage::log_info("MetaModel::Startup (ModelOnly = $bModelOnly)");
|
||||
}
|
||||
|
||||
if (!$bUseCache)
|
||||
{
|
||||
// Reset the cache for the first use !
|
||||
MetaModel::ResetCache($oConfig);
|
||||
}
|
||||
|
||||
MetaModel::Startup($oConfig, $bModelOnly, $bUseCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes the current installation and the possibilities
|
||||
*
|
||||
* @param $oConfig Config Defines the target environment (DB)
|
||||
* @return hash Array with the following format:
|
||||
* array =>
|
||||
* 'iTop' => array(
|
||||
* 'version_db' => ... (could be empty in case of a fresh install)
|
||||
* 'version_code => ...
|
||||
* )
|
||||
* <module_name> => array(
|
||||
* 'version_db' => ...
|
||||
* 'version_code' => ...
|
||||
* 'install' => array(
|
||||
* 'flag' => SETUP_NEVER | SETUP_OPTIONAL | SETUP_MANDATORY
|
||||
* 'message' => ...
|
||||
* )
|
||||
* 'uninstall' => array(
|
||||
* 'flag' => SETUP_NEVER | SETUP_OPTIONAL | SETUP_MANDATORY
|
||||
* 'message' => ...
|
||||
* )
|
||||
* 'label' => ...
|
||||
* 'dependencies' => array(<module1>, <module2>, ...)
|
||||
* 'visible' => true | false
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
function AnalyzeInstallation($oConfig, $sModulesRelativePath)
|
||||
{
|
||||
$aRes = array(
|
||||
ROOT_MODULE => array(
|
||||
'version_db' => '',
|
||||
'name_db' => '',
|
||||
'version_code' => ITOP_VERSION.'.'.ITOP_REVISION,
|
||||
'name_code' => ITOP_APPLICATION,
|
||||
)
|
||||
);
|
||||
|
||||
$aModules = ModuleDiscovery::GetAvailableModules(APPROOT, $sModulesRelativePath);
|
||||
foreach($aModules as $sModuleId => $aModuleInfo)
|
||||
{
|
||||
list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId);
|
||||
|
||||
$sModuleAppVersion = $aModuleInfo['itop_version'];
|
||||
$aModuleInfo['version_db'] = '';
|
||||
$aModuleInfo['version_code'] = $sModuleVersion;
|
||||
|
||||
if (!in_array($sModuleAppVersion, array('1.0.0', '1.0.1', '1.0.2')))
|
||||
{
|
||||
// This module is NOT compatible with the current version
|
||||
$aModuleInfo['install'] = array(
|
||||
'flag' => MODULE_ACTION_IMPOSSIBLE,
|
||||
'message' => 'the module is not compatible with the current version of the application'
|
||||
);
|
||||
}
|
||||
elseif ($aModuleInfo['mandatory'])
|
||||
{
|
||||
$aModuleInfo['install'] = array(
|
||||
'flag' => MODULE_ACTION_MANDATORY,
|
||||
'message' => 'the module is part of the application'
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aModuleInfo['install'] = array(
|
||||
'flag' => MODULE_ACTION_OPTIONAL,
|
||||
'message' => ''
|
||||
);
|
||||
}
|
||||
$aRes[$sModuleName] = $aModuleInfo;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
CMDBSource::Init($oConfig->GetDBHost(), $oConfig->GetDBUser(), $oConfig->GetDBPwd(), $oConfig->GetDBName());
|
||||
$aSelectInstall = CMDBSource::QueryToArray("SELECT * FROM ".$oConfig->GetDBSubname()."priv_module_install");
|
||||
}
|
||||
catch (MySQLException $e)
|
||||
{
|
||||
// No database or eroneous information
|
||||
$aSelectInstall = array();
|
||||
}
|
||||
|
||||
// Build the list of installed module (get the latest installation)
|
||||
//
|
||||
$aInstallByModule = array(); // array of <module> => array ('installed' => timestamp, 'version' => <version>)
|
||||
foreach ($aSelectInstall as $aInstall)
|
||||
{
|
||||
//$aInstall['comment']; // unsused
|
||||
$iInstalled = strtotime($aInstall['installed']);
|
||||
$sModuleName = $aInstall['name'];
|
||||
$sModuleVersion = $aInstall['version'];
|
||||
|
||||
if ($aInstall['parent_id'] == 0)
|
||||
{
|
||||
$sModuleName = ROOT_MODULE;
|
||||
}
|
||||
|
||||
if (array_key_exists($sModuleName, $aInstallByModule))
|
||||
{
|
||||
if ($iInstalled < $aInstallByModule[$sModuleName]['installed'])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($aInstall['parent_id'] == 0)
|
||||
{
|
||||
$aRes[$sModuleName]['version_db'] = $sModuleVersion;
|
||||
$aRes[$sModuleName]['name_db'] = $aInstall['name'];
|
||||
}
|
||||
|
||||
$aInstallByModule[$sModuleName]['installed'] = $iInstalled;
|
||||
$aInstallByModule[$sModuleName]['version'] = $sModuleVersion;
|
||||
}
|
||||
|
||||
// Adjust the list of proposed modules
|
||||
//
|
||||
foreach ($aInstallByModule as $sModuleName => $aModuleDB)
|
||||
{
|
||||
if ($sModuleName == ROOT_MODULE) continue; // Skip the main module
|
||||
|
||||
if (!array_key_exists($sModuleName, $aRes))
|
||||
{
|
||||
// A module was installed, it is not proposed in the new build... skip
|
||||
continue;
|
||||
}
|
||||
$aRes[$sModuleName]['version_db'] = $aModuleDB['version'];
|
||||
|
||||
if ($aRes[$sModuleName]['install']['flag'] == MODULE_ACTION_MANDATORY)
|
||||
{
|
||||
$aRes[$sModuleName]['uninstall'] = array(
|
||||
'flag' => MODULE_ACTION_IMPOSSIBLE,
|
||||
'message' => 'the module is part of the application'
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aRes[$sModuleName]['uninstall'] = array(
|
||||
'flag' => MODULE_ACTION_OPTIONAL,
|
||||
'message' => ''
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $aRes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create the database structure
|
||||
* @return boolean true on success, false otherwise
|
||||
*/
|
||||
function CreateDatabaseStructure(Config $oConfig, $sMode)
|
||||
{
|
||||
if (strlen($oConfig->GetDBSubname()) > 0)
|
||||
{
|
||||
SetupPage::log_info("Creating the structure in '".$oConfig->GetDBName()."' (table names prefixed by '".$oConfig->GetDBSubname()."').");
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupPage::log_info("Creating the structure in '".$oConfig->GetDBSubname()."'.");
|
||||
}
|
||||
|
||||
//MetaModel::CheckDefinitions();
|
||||
if ($sMode == 'install')
|
||||
{
|
||||
if (!MetaModel::DBExists(/* bMustBeComplete */ false))
|
||||
{
|
||||
MetaModel::DBCreate();
|
||||
SetupPage::log_ok("Database structure successfully created.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen($oConfig->GetDBSubname()) > 0)
|
||||
{
|
||||
throw new Exception("Error: found iTop tables into the database '".$oConfig->GetDBName()."' (prefix: '".$oConfig->GetDBSubname()."'). Please, try selecting another database instance or specify another prefix to prevent conflicting table names.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Error: found iTop tables into the database '".$oConfig->GetDBName()."'. Please, try selecting another database instance or specify a prefix to prevent conflicting table names.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MetaModel::DBExists(/* bMustBeComplete */ false))
|
||||
{
|
||||
MetaModel::DBCreate();
|
||||
SetupPage::log_ok("Database structure successfully updated.");
|
||||
|
||||
// Check (and update only if it seems needed) the hierarchical keys
|
||||
ob_start();
|
||||
MetaModel::CheckHKeys(false /* bDiagnosticsOnly */, true /* bVerbose*/, true /* bForceUpdate */); // Since in 1.2-beta the detection was buggy, let's force the rebuilding of HKeys
|
||||
$sFeedback = ob_get_clean();
|
||||
SetupPage::log_ok("Hierchical keys rebuilt: $sFeedback");
|
||||
|
||||
// Check (and fix) data sync configuration
|
||||
ob_start();
|
||||
MetaModel::CheckDataSources(false /*$bDiagnostics*/, true/*$bVerbose*/);
|
||||
$sFeedback = ob_get_clean();
|
||||
SetupPage::log_ok("Data sources checked: $sFeedback");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen($oConfig->GetDBSubname()) > 0)
|
||||
{
|
||||
throw new Exception("Error: No previous instance of iTop found into the database '".$oConfig->GetDBName()."' (prefix: '".$oConfig->GetDBSubname()."'). Please, try selecting another database instance.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Error: No previous instance of iTop found into the database '".$oConfig->GetDBName()."'. Please, try selecting another database instance.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function RecordInstallation(Config $oConfig, $aSelectedModules, $sModulesRelativePath)
|
||||
{
|
||||
// Record main installation
|
||||
$oInstallRec = new ModuleInstallation();
|
||||
$oInstallRec->Set('name', ITOP_APPLICATION);
|
||||
$oInstallRec->Set('version', ITOP_VERSION.'.'.ITOP_REVISION);
|
||||
$oInstallRec->Set('comment', "Done by the setup program\nBuilt on ".ITOP_BUILD_DATE);
|
||||
$oInstallRec->Set('parent_id', 0); // root module
|
||||
$iMainItopRecord = $oInstallRec->DBInsertNoReload();
|
||||
|
||||
// Record installed modules
|
||||
//
|
||||
$aAvailableModules = AnalyzeInstallation($oConfig, $sModulesRelativePath);
|
||||
foreach($aSelectedModules as $sModuleId)
|
||||
{
|
||||
$aModuleData = $aAvailableModules[$sModuleId];
|
||||
$sName = $sModuleId;
|
||||
$sVersion = $aModuleData['version_code'];
|
||||
$aComments = array();
|
||||
$aComments[] = 'Done by the setup program';
|
||||
if ($aModuleData['mandatory'])
|
||||
{
|
||||
$aComments[] = 'Mandatory';
|
||||
}
|
||||
else
|
||||
{
|
||||
$aComments[] = 'Optional';
|
||||
}
|
||||
if ($aModuleData['visible'])
|
||||
{
|
||||
$aComments[] = 'Visible (during the setup)';
|
||||
}
|
||||
else
|
||||
{
|
||||
$aComments[] = 'Hidden (selected automatically)';
|
||||
}
|
||||
foreach ($aModuleData['dependencies'] as $sDependOn)
|
||||
{
|
||||
$aComments[] = "Depends on module: $sDependOn";
|
||||
}
|
||||
$sComment = implode("\n", $aComments);
|
||||
|
||||
$oInstallRec = new ModuleInstallation();
|
||||
$oInstallRec->Set('name', $sName);
|
||||
$oInstallRec->Set('version', $sVersion);
|
||||
$oInstallRec->Set('comment', $sComment);
|
||||
$oInstallRec->Set('parent_id', $iMainItopRecord);
|
||||
$oInstallRec->DBInsertNoReload();
|
||||
}
|
||||
// Database is created, installation has been tracked into it
|
||||
return true;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
Reference in New Issue
Block a user