public static function log_error($sText) { SetupPage::log_error($sText); }
/** * Store an object in the database and remember the mapping * between its original ID and the newly created ID in the database */ protected function StoreObject($sClass, $oTargetObj, $iSrcId, $bSearch = false, $bUpdateKeyCacheOnly = false) { $iObjId = 0; try { if ($bSearch) { // Check if the object does not already exist, based on its usual reconciliation keys... $aReconciliationKeys = MetaModel::GetReconcKeys($sClass); if (count($aReconciliationKeys) > 0) { // Some reconciliation keys have been defined, use them to search for the object $oSearch = new DBObjectSearch($sClass); $iConditionsCount = 0; foreach ($aReconciliationKeys as $sAttCode) { if ($oTargetObj->Get($sAttCode) != '') { $oSearch->AddCondition($sAttCode, $oTargetObj->Get($sAttCode), '='); $iConditionsCount++; } } if ($iConditionsCount > 0) { $oSet = new DBObjectSet($oSearch); if ($oSet->count() == 1) { // The object already exists, reuse it $oExistingObject = $oSet->Fetch(); $iObjId = $oExistingObject->GetKey(); } } } } if ($iObjId == 0) { if ($oTargetObj->IsNew()) { if (!$bUpdateKeyCacheOnly) { $iObjId = $oTargetObj->DBInsertNoReload(); $this->m_iCountCreated++; } } else { $iObjId = $oTargetObj->GetKey(); if (!$bUpdateKeyCacheOnly) { $oTargetObj->DBUpdate(); } } } } catch (Exception $e) { SetupPage::log_error("An object could not be recorded - {$sClass}/{$iSrcId} - " . $e->getMessage()); $this->m_aErrors[] = "An object could not be recorded - {$sClass}/{$iSrcId} - " . $e->getMessage(); } $aParentClasses = MetaModel::EnumParentClasses($sClass); $aParentClasses[] = $sClass; foreach ($aParentClasses as $sObjClass) { $this->m_aKeys[$sObjClass][$iSrcId] = $iObjId; } $this->m_aObjectsCache[$sClass][$iObjId] = $oTargetObj; }
$oPage = new ajax_page(''); $oDummyController = new WizardController(''); if (is_subclass_of($sClass, 'WizardStep')) { $oStep = new $sClass($oDummyController, $sState); $sConfigFile = utils::GetConfigFilePath(); if (file_exists($sConfigFile) && !is_writable($sConfigFile) && $oStep->RequiresWritableConfig()) { $oPage->error("<b>Error:</b> the configuration file '" . $sConfigFile . "' already exists and cannot be overwritten."); $oPage->p("The wizard cannot modify the configuration file for you. If you want to upgrade " . ITOP_APPLICATION . ", make sure that the file '<b>" . realpath($sConfigFile) . "</b>' can be modified by the web server."); $oPage->output(); } else { $oStep->AsyncAction($oPage, $sActionCode, $aParams); } } $oPage->output(); break; default: throw new Exception("Error unsupported operation '{$sOperation}'"); } } catch (Exception $e) { header("HTTP/1.0 500 Internal server error."); echo "<p>An error happened while processing the installation:</p>\n"; echo '<p>' . $e . "</p>\n"; SetupPage::log_error("An error happened while processing the installation: " . $e); } if (function_exists('memory_get_peak_usage')) { if ($sOperation == 'file') { SetupPage::log_info("loading file '{$sFileName}', peak memory usage. " . memory_get_peak_usage()); } else { SetupPage::log_info("operation '{$sOperation}', peak memory usage. " . memory_get_peak_usage()); } }
/** * Wrappers for logging into the setup log files */ protected function log_error($sText) { SetupPage::log_error($sText); }
protected static function DoUpdateDBSchema($sMode, $aSelectedModules, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTargetEnvironment = '', $bOldAddon = false) { SetupPage::log_info("Update Database Schema for environment '{$sTargetEnvironment}'."); $oConfig = new Config(); $aParamValues = array('mode' => $sMode, 'db_server' => $sDBServer, 'db_user' => $sDBUser, 'db_pwd' => $sDBPwd, 'db_name' => $sDBName, 'db_prefix' => $sDBPrefix); $oConfig->UpdateFromParams($aParamValues, $sModulesDir); if ($bOldAddon) { // Old version of the add-on for backward compatibility with pre-2.0 data models $oConfig->SetAddons(array('user rights' => 'addons/userrights/userrightsprofile.db.class.inc.php')); } $oProductionEnv = new RunTimeEnvironment($sTargetEnvironment); $oProductionEnv->InitDataModel($oConfig, true); // load data model only // Migrate application data format // // priv_internalUser caused troubles because MySQL transforms table names to lower case under Windows // This becomes an issue when moving your installation data to/from Windows // Starting 2.0, all table names must be lowercase if ($sMode != 'install') { SetupPage::log_info("Renaming '{$sDBPrefix}priv_internalUser' into '{$sDBPrefix}priv_internaluser' (lowercase)"); // This command will have no effect under Windows... // and it has been written in two steps so as to make it work under windows! CMDBSource::SelectDB($sDBName); try { $sRepair = "RENAME TABLE `{$sDBPrefix}priv_internalUser` TO `{$sDBPrefix}priv_internaluser_other`, `{$sDBPrefix}priv_internaluser_other` TO `{$sDBPrefix}priv_internaluser`"; CMDBSource::Query($sRepair); } catch (Exception $e) { SetupPage::log_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 SetupPage::log_info("Cleanup of '{$sDBPrefix}priv_change' to remove orphan records"); CMDBSource::SelectDB($sDBName); try { $sTotalCount = "SELECT COUNT(*) FROM `{$sDBPrefix}priv_change`"; $iTotalCount = (int) CMDBSource::QueryToScalar($sTotalCount); SetupPage::log_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"; $iOrphanCount = (int) CMDBSource::QueryToScalar($sOrphanCount); SetupPage::log_info("There are {$iOrphanCount} useless records in {$sDBPrefix}priv_change (" . sprintf('%.2f', 100.0 * $iOrphanCount / $iTotalCount) . "%)"); if ($iOrphanCount > 0) { SetupPage::log_info("Removing the orphan records..."); $sCleanup = "DELETE FROM `{$sDBPrefix}priv_change` USING `{$sDBPrefix}priv_change` LEFT JOIN `{$sDBPrefix}priv_changeop` ON `{$sDBPrefix}priv_change`.id = `{$sDBPrefix}priv_changeop`.changeid WHERE `{$sDBPrefix}priv_changeop`.id IS NULL;"; CMDBSource::Query($sCleanup); SetupPage::log_info("Cleanup completed successfully."); } else { SetupPage::log_info("Ok, nothing to cleanup."); } } catch (Exception $e) { SetupPage::log_info("Cleanup of orphan records in `{$sDBPrefix}priv_change` failed: " . $e->getMessage()); } } // Module specific actions (migrate the data) // $aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), APPROOT . $sModulesDir); foreach ($aAvailableModules as $sModuleId => $aModule) { if ($sModuleId != ROOT_MODULE && in_array($sModuleId, $aSelectedModules) && isset($aAvailableModules[$sModuleId]['installer'])) { $sModuleInstallerClass = $aAvailableModules[$sModuleId]['installer']; SetupPage::log_info("Calling Module Handler: {$sModuleInstallerClass}::BeforeDatabaseCreation(oConfig, {$aModule['version_db']}, {$aModule['version_code']})"); $aCallSpec = array($sModuleInstallerClass, 'BeforeDatabaseCreation'); call_user_func_array($aCallSpec, array(MetaModel::GetConfig(), $aModule['version_db'], $aModule['version_code'])); } } if (!$oProductionEnv->CreateDatabaseStructure(MetaModel::GetConfig(), $sMode)) { throw new Exception("Failed to create/upgrade the database structure for environment '{$sTargetEnvironment}'"); } // 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 // Then check if some records should hold a different value, based on a pattern matching in the userinfo field CMDBSource::SelectDB($sDBName); try { $sCount = "SELECT COUNT(*) FROM `{$sDBPrefix}priv_change` WHERE `origin` IS NULL"; $iCount = (int) CMDBSource::QueryToScalar($sCount); if ($iCount > 0) { SetupPage::log_info("Initializing '{$sDBPrefix}priv_change.origin' ({$iCount} records to update)"); // By default all uninitialized values are considered as 'interactive' $sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'interactive' WHERE `origin` IS NULL"; CMDBSource::Query($sInit); // 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)'"; CMDBSource::Query($sInit); // 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'"; CMDBSource::Query($sInit); // 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 $sCurrentLanguage = Dict::GetUserLanguage(); foreach (Dict::GetLanguages() as $sLangCode => $aLang) { Dict::SetUserLanguage($sLangCode); $sSuffix = CMDBSource::Quote('%' . Dict::S('Core:SyncDataExchangeComment')); $aSuffixes[$sSuffix] = true; } Dict::SetUserLanguage($sCurrentLanguage); $sCondition = "`userinfo` LIKE " . implode(" OR `userinfo` LIKE ", array_keys($aSuffixes)); $sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'synchro-data-source' WHERE ({$sCondition})"; CMDBSource::Query($sInit); SetupPage::log_info("Initialization of '{$sDBPrefix}priv_change.origin' completed."); } else { SetupPage::log_info("'{$sDBPrefix}priv_change.origin' already initialized, nothing to do."); } } catch (Exception $e) { SetupPage::log_error("Initializing '{$sDBPrefix}priv_change.origin' failed: " . $e->getMessage()); } // priv_async_task now has a 'status' field to distinguish between the various statuses rather than just relying on the date columns // Let's initialize the field with 'planned' or 'error' for all records were it's null CMDBSource::SelectDB($sDBName); try { $sCount = "SELECT COUNT(*) FROM `{$sDBPrefix}priv_async_task` WHERE `status` IS NULL"; $iCount = (int) CMDBSource::QueryToScalar($sCount); if ($iCount > 0) { SetupPage::log_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)"; CMDBSource::Query($sInit); $sInit = "UPDATE `{$sDBPrefix}priv_async_task` SET `status` = 'error' WHERE (`status` IS NULL) AND (`started` IS NOT NULL)"; CMDBSource::Query($sInit); SetupPage::log_info("Initialization of '{$sDBPrefix}priv_async_task.status' completed."); } else { SetupPage::log_info("'{$sDBPrefix}priv_async_task.status' already initialized, nothing to do."); } } catch (Exception $e) { SetupPage::log_error("Initializing '{$sDBPrefix}priv_async_task.status' failed: " . $e->getMessage()); } SetupPage::log_info("Database Schema Successfully Updated for environment '{$sTargetEnvironment}'."); }