public function DBInsertNoReload() { $oMutex = new iTopMutex('ticket_insert'); $oMutex->Lock(); $iNextId = MetaModel::GetNextKey(get_class($this)); $sRef = $this->MakeTicketRef($iNextId); $this->Set('ref', $sRef); $iKey = parent::DBInsertNoReload(); $oMutex->Unlock(); return $iKey; }
$oPage->output(); break; case 'restore_exec': require_once APPROOT . "setup/runtimeenv.class.inc.php"; require_once APPROOT . '/application/utils.inc.php'; require_once APPROOT . '/setup/backup.class.inc.php'; require_once dirname(__FILE__) . '/dbrestore.class.inc.php'; IssueLog::Enable(APPROOT . 'log/error.log'); $oPage = new ajax_page(""); $oPage->no_cache(); $oPage->SetContentType('text/html'); if (utils::GetConfig()->Get('demo_mode')) { $oPage->add("<div data-error-stimulus=\"Error\">Sorry, iTop is in <b>demonstration mode</b>: the feature is disabled.</div>"); } else { $sEnvironment = utils::ReadParam('environment', 'production', false, 'raw_data'); $oRestoreMutex = new iTopMutex('restore.' . $sEnvironment); IssueLog::Info("Backup Restore - Acquiring the LOCK 'restore.{$sEnvironment}'"); $oRestoreMutex->Lock(); IssueLog::Info('Backup Restore - LOCK acquired, executing...'); try { set_time_limit(0); // Get the file and destroy the token (single usage) $sToken = utils::ReadParam('token', '', false, 'raw_data'); $sTokenFile = APPROOT . '/data/restore.' . $sToken . '.tok'; if (!is_file($sTokenFile)) { throw new Exception("Error: missing token file: '{$sTokenFile}'"); } $sFile = file_get_contents($sTokenFile); unlink($sTokenFile); $sMySQLBinDir = utils::ReadParam('mysql_bindir', '', false, 'raw_data'); $sDBHost = utils::ReadParam('db_host', '', false, 'raw_data');
////////////////////////////////////////////////// // // Go for parsing and interpretation // try { $oP->add_comment('Load--------------'); $oP->add_comment('------------------'); if ($bSimulate) { CMDBSource::Query('START TRANSACTION'); } $aData = $oCSVParser->ToArray(); $iLineCount = count($aData); $sTable = $oDataSource->GetDataTable(); // Prepare insert columns $sInsertColumns = '`' . implode('`, `', $aInputColumns) . '`'; $oMutex = new iTopMutex('synchro_import_' . $oDataSource->GetKey()); $oMutex->Lock(); foreach ($aData as $iRow => $aRow) { $sReconciliationCondition = "`primary_key` = " . CMDBSource::Quote($aRow[$iPrimaryKeyCol]); $sSelect = "SELECT COUNT(*) FROM `{$sTable}` WHERE {$sReconciliationCondition}"; $aRes = CMDBSource::QueryToArray($sSelect); $iCount = $aRes[0]['COUNT(*)']; if ($iCount == 0) { // No record... create it // $iCountCreations++; if ($sOutput == 'details') { $oP->add("{$iRow}: New entry, reconciliation: '{$sReconciliationCondition}'\n"); } $aValues = array(); // Used to build the insert query
foreach ($aProcesses as $oExecInstance) { $aDisplayProcesses[] = get_class($oExecInstance); } $sDisplayProcesses = implode(', ', $aDisplayProcesses); $oP->p("Background processes: " . $sDisplayProcesses); } if (utils::ReadParam('status_only', false, true)) { // Display status and exit DisplayStatus($oP); exit(0); } require_once APPROOT . 'core/mutex.class.inc.php'; $oP->p("Starting: " . time() . ' (' . date('Y-m-d H:i:s') . ')'); try { $oConfig = utils::GetConfig(); $oMutex = new iTopMutex('cron.' . $oConfig->GetDBName() . '_' . $oConfig->GetDBSubname()); if ($oMutex->TryLock()) { // Note: testing this now in case some of the background processes forces the read-only mode for a while // in that case it is better to exit with the check on reentrance (mutex) if (!MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE)) { $oP->p("A database maintenance is ongoing (read-only mode even for admins)."); $oP->Output(); exit - 1; } CronExec($oP, $aProcesses, $bVerbose); $oMutex->Unlock(); } else { // Exit silently $oP->p("Already running..."); } } catch (Exception $e) {
/** * Perform a synchronization between the data stored in the replicas (&synchro_data_xxx_xx table) * and the iTop objects. If the lastFullLoadStartDate is NOT specified then the full_load_periodicity * is used to determine which records are obsolete. * @return void */ public function Process() { $this->PrepareLogs(); self::$m_oCurrentTask = $this->m_oDataSource; $oMutex = new iTopMutex('synchro_process_' . $this->m_oDataSource->GetKey()); try { $oMutex->Lock(); $this->DoSynchronize(); $oMutex->Unlock(); $this->m_oStatLog->Set('end_date', time()); $this->m_oStatLog->Set('status', 'completed'); $this->m_oStatLog->DBUpdateTracked($this->m_oChange); $iErrors = $this->m_oStatLog->GetErrorCount(); if ($iErrors > 0) { $sIssuesOQL = "SELECT SynchroReplica WHERE sync_source_id=" . $this->m_oDataSource->GetKey() . " AND status_last_error!=''"; $sAbsoluteUrl = utils::GetAbsoluteUrlAppRoot(); $sIssuesURL = "{$sAbsoluteUrl}synchro/replica.php?operation=oql&datasource=" . $this->m_oDataSource->GetKey() . "&oql=" . urlencode($sIssuesOQL); $sSeeIssues = "<p></p>"; $sStatistics = "<h1>Statistics</h1>\n"; $sStatistics .= "<ul>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('start_date') . ": " . $this->m_oStatLog->Get('start_date') . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('end_date') . ": " . $this->m_oStatLog->Get('end_date') . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_replica_seen') . ": " . $this->m_oStatLog->Get('stats_nb_replica_seen') . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_replica_total') . ": " . $this->m_oStatLog->Get('stats_nb_replica_total') . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_obj_deleted') . ": " . $this->m_oStatLog->Get('stats_nb_obj_deleted') . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_obj_deleted_errors') . ": " . $this->m_oStatLog->Get('stats_nb_obj_deleted_errors') . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_obj_obsoleted') . ": " . $this->m_oStatLog->Get('stats_nb_obj_obsoleted') . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_obj_obsoleted_errors') . ": " . $this->m_oStatLog->Get('stats_nb_obj_obsoleted_errors') . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_obj_created') . ": " . $this->m_oStatLog->Get('stats_nb_obj_created') . " (" . $this->m_oStatLog->Get('stats_nb_obj_created_warnings') . " warnings)" . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_obj_created_errors') . ": " . $this->m_oStatLog->Get('stats_nb_obj_created_errors') . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_obj_updated') . ": " . $this->m_oStatLog->Get('stats_nb_obj_updated') . " (" . $this->m_oStatLog->Get('stats_nb_obj_updated_warnings') . " warnings)" . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_obj_updated_errors') . ": " . $this->m_oStatLog->Get('stats_nb_obj_updated_errors') . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_replica_reconciled_errors') . ": " . $this->m_oStatLog->Get('stats_nb_replica_reconciled_errors') . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_replica_disappeared_no_action') . ": " . $this->m_oStatLog->Get('stats_nb_replica_disappeared_no_action') . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_obj_new_updated') . ": " . $this->m_oStatLog->Get('stats_nb_obj_new_updated') . " (" . $this->m_oStatLog->Get('stats_nb_obj_new_updated_warnings') . " warnings)" . "</li>\n"; $sStatistics .= "<li>" . $this->m_oStatLog->GetLabel('stats_nb_obj_new_unchanged') . ": " . $this->m_oStatLog->Get('stats_nb_obj_new_unchanged') . " (" . $this->m_oStatLog->Get('stats_nb_obj_new_unchanged_warnings') . " warnings)" . "</li>\n"; $sStatistics .= "</ul>\n"; $this->m_oDataSource->SendNotification("errors ({$iErrors})", "<p>The synchronization has been executed, {$iErrors} errors have been encountered. Click <a href=\"{$sIssuesURL}\">here</a> to see the records being currently in error.</p>" . $sStatistics); } else { //$this->m_oDataSource->SendNotification('success', '<p>The synchronization has been successfully executed.</p>'); } } catch (SynchroExceptionNotStarted $e) { $oMutex->Unlock(); // Set information for reporting... but delete the object in DB $this->m_oStatLog->Set('end_date', time()); $this->m_oStatLog->Set('status', 'error'); $this->m_oStatLog->Set('last_error', $e->getMessage()); $this->m_oStatLog->DBDeleteTracked($this->m_oChange); $this->m_oDataSource->SendNotification('fatal error', '<p>The synchronization could not start: \'' . $e->getMessage() . '\'</p><p>Please check its configuration</p>'); } catch (Exception $e) { $oMutex->Unlock(); $this->m_oStatLog->Set('end_date', time()); $this->m_oStatLog->Set('status', 'error'); $this->m_oStatLog->Set('last_error', $e->getMessage()); $this->m_oStatLog->DBUpdateTracked($this->m_oChange); $this->m_oDataSource->SendNotification('exception', '<p>The synchronization has been interrupted: \'' . $e->getMessage() . '\'</p><p>Please contact the application support team</p>'); } self::$m_oCurrentTask = null; return $this->m_oStatLog; }
public function Process($iUnixTimeLimit) { $oMutex = new iTopMutex('backup.' . utils::GetCurrentEnvironment()); $oMutex->Lock(); try { // Make sure the target directory exists SetupUtils::builddir($this->sBackupDir); $oBackup = new DBBackupScheduled(); // Eliminate files exceeding the retention setting // if ($this->iRetentionCount > 0) { $aFiles = $oBackup->ListFiles($this->sBackupDir); while (count($aFiles) >= $this->iRetentionCount) { $sFileToDelete = array_shift($aFiles); unlink($sFileToDelete); if (file_exists($sFileToDelete)) { // Ok, do not loop indefinitely on this break; } } } // Do execute the backup // $oBackup->SetMySQLBinDir(MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', '')); $sBackupFile = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'file_name_format', '__DB__-%Y-%m-%d_%H_%M'); $sName = $oBackup->MakeName($sBackupFile); if ($sName == '') { $sName = $oBackup->MakeName(BACKUP_DEFAULT_FORMAT); } $sZipFile = $this->sBackupDir . $sName . '.zip'; $sSourceConfigFile = APPCONF . utils::GetCurrentEnvironment() . '/' . ITOP_CONFIG_FILE; $oBackup->CreateZip($sZipFile, $sSourceConfigFile); } catch (Exception $e) { $oMutex->Unlock(); throw $e; } $oMutex->Unlock(); return "Created the backup: {$sZipFile}"; }
public function Display(WebPage $oPage) { $oPage->add_style(<<<EOF #changes_summary { \tmax-height: 200px; \toverflow: auto; } #changes_summary div { \twidth:100; \tmargin-top:0; \tpadding-top: 0.5em; \tpadding-left: 0; } #changes_summary div ul { \tmargin-left:0; \tpadding-left: 20px; } #changes_summary div.closed ul { \tdisplay:none; } #changes_summary div li { \tlist-style: none; \twidth: 100; \tmargin-left:0; \tpadding-left: 0em; } .title { \tpadding-left: 20px; \tfont-weight: bold; \tcursor: pointer; \tbackground: url(../images/minus.gif) 2px 2px no-repeat; } #changes_summary div.closed .title { \tbackground: url(../images/plus.gif) 2px 2px no-repeat; } EOF ); $this->bCanMoveForward = true; $bDisplayLicense = true; $sPreviousVersionDir = $this->oWizard->GetParameter('previous_version_dir', ''); $aInstalledInfo = SetupUtils::GetApplicationVersion($this->oWizard); if ($aInstalledInfo === false) { throw new Exception('No previous version of ' . ITOP_APPLICATION . ' found in the supplied database. The upgrade cannot continue.'); } else { if (strcasecmp($aInstalledInfo['product_name'], ITOP_APPLICATION) != 0) { $oPage->p("<b>Warning: The installed products seem different. Are you sure the you want to upgrade {$aInstalledInfo['product_name']} with " . ITOP_APPLICATION . "?</b>"); } } $sInstalledVersion = $aInstalledInfo['product_version']; $sInstalledDataModelVersion = $aInstalledInfo['datamodel_version']; $oPage->add("<h2>Information about the upgrade from version {$sInstalledVersion} to " . ITOP_VERSION . '.' . ITOP_REVISION . "</h2>"); if ($sInstalledVersion == ITOP_VERSION . '.' . ITOP_REVISION) { // Reinstalling the same version let's skip the license agreement... $bDisplayLicense = false; } $this->oWizard->SetParameter('license', $bDisplayLicense); // Remember for later if ($sInstalledDataModelVersion == '$ITOP_VERSION$.$WCREV$') { // Special case for upgrading some development versions (temporary) $sCompatibleDMDir = SetupUtils::GetLatestDataModelDir(); $sInstalledDataModelVersion = SetupUtils::GetDataModelVersion($sCompatibleDMDir); } else { $sCompatibleDMDir = SetupUtils::GetCompatibleDataModelDir($sInstalledDataModelVersion); } if ($sCompatibleDMDir === false) { // No compatible version exists... cannot upgrade. Either it is too old, or too new (downgrade !) $this->bCanMoveForward = false; $oPage->p("The current version of " . ITOP_APPLICATION . " (" . ITOP_VERSION . '.' . ITOP_REVISION . ") does not seem to be compatible with the installed version ({$sInstalledVersion})."); $oPage->p("The upgrade cannot continue, sorry."); } else { $sUpgradeDMVersion = SetupUtils::GetDataModelVersion($sCompatibleDMDir); $sPreviousSourceDir = isset($aInstalledInfo['source_dir']) ? $aInstalledInfo['source_dir'] : 'modules'; $aChanges = false; if (is_dir($sPreviousVersionDir)) { // Check if the previous version is a "genuine" one or not... $aChanges = SetupUtils::CheckVersion($sInstalledDataModelVersion, $sPreviousVersionDir . '/' . $sPreviousSourceDir); } if ($aChanges !== false && (count($aChanges['added']) > 0 || count($aChanges['removed']) > 0 || count($aChanges['modified']) > 0)) { // Some changes were detected, prompt the user to keep or discard them $oPage->p("<img src=\"../images/error.png\"/> Some modifications were detected between the " . ITOP_APPLICATION . " version in '{$sPreviousVersionDir}' and a genuine {$sInstalledVersion} version."); $oPage->p("What do you want to do?"); $aWritableDirs = array('modules', 'portal'); $aErrors = SetupUtils::CheckWritableDirs($aWritableDirs); $sChecked = $this->oWizard->GetParameter('upgrade_type') == 'keep-previous' ? ' checked ' : ''; $sDisabled = count($aErrors) > 0 ? ' disabled ' : ''; $oPage->p('<input id="radio_upgrade_keep" type="radio" name="upgrade_type" value="keep-previous"' . $sChecked . $sDisabled . '/><label for="radio_upgrade_keep"> Preserve the modifications of the installed version (the dasboards inside ' . ITOP_APPLICATION . ' may not be editable).</label>'); $oPage->add('<input type="hidden" name="datamodel_previous_version" value="' . htmlentities($sInstalledDataModelVersion, ENT_QUOTES, 'UTF-8') . '">'); $oPage->add('<input type="hidden" name="relative_source_dir" value="' . htmlentities($sPreviousSourceDir, ENT_QUOTES, 'UTF-8') . '">'); if (count($aErrors) > 0) { $oPage->p("Cannot copy the installed version due to the following access rights issue(s):"); foreach ($aErrors as $sDir => $oCheckResult) { $oPage->p('<img src="../images/error.png"/> ' . $oCheckResult->sLabel); } } $sChecked = $this->oWizard->GetParameter('upgrade_type') == 'use-compatible' ? ' checked ' : ''; $oPage->p('<input id="radio_upgrade_convert" type="radio" name="upgrade_type" value="use-compatible"' . $sChecked . '/><label for="radio_upgrade_convert"> Discard the modifications, use a standard ' . $sUpgradeDMVersion . ' data model.</label>'); $oPage->add('<input type="hidden" name="datamodel_path" value="' . htmlentities($sCompatibleDMDir, ENT_QUOTES, 'UTF-8') . '">'); $oPage->add('<input type="hidden" name="datamodel_version" value="' . htmlentities($sUpgradeDMVersion, ENT_QUOTES, 'UTF-8') . '">'); $oPage->add('<div id="changes_summary"><div class="closed"><span class="title">Details of the modifications</span><div>'); if (count($aChanges['added']) > 0) { $oPage->add('<ul>New files added:'); foreach ($aChanges['added'] as $sFilePath => $void) { $oPage->add('<li>' . $sFilePath . '</li>'); } $oPage->add('</ul>'); } if (count($aChanges['removed']) > 0) { $oPage->add('<ul>Deleted files:'); foreach ($aChanges['removed'] as $sFilePath => $void) { $oPage->add('<li>' . $sFilePath . '</li>'); } $oPage->add('</ul>'); } if (count($aChanges['modified']) > 0) { $oPage->add('<ul>Modified files:'); foreach ($aChanges['modified'] as $sFilePath => $void) { $oPage->add('<li>' . $sFilePath . '</li>'); } $oPage->add('</ul>'); } $oPage->add('</div></div></div>'); } else { // No changes detected... or no way to tell because of the lack of a manifest or previous source dir // Use the "compatible" datamodel as-is. $oPage->p("<img src=\"../images/validation_ok.png\"/> The datamodel will be upgraded from version {$sInstalledDataModelVersion} to version {$sUpgradeDMVersion}."); $oPage->add('<input type="hidden" name="upgrade_type" value="use-compatible">'); $oPage->add('<input type="hidden" name="datamodel_path" value="' . htmlentities($sCompatibleDMDir, ENT_QUOTES, 'UTF-8') . '">'); $oPage->add('<input type="hidden" name="datamodel_version" value="' . htmlentities($sUpgradeDMVersion, ENT_QUOTES, 'UTF-8') . '">'); } // Check if there are "extensions" to preserve and if it's possible if (is_dir($sPreviousVersionDir . '/extensions')) { $aExtensions = glob($sPreviousVersionDir . '/extensions/*', GLOB_ONLYDIR); if ($aExtensions !== false && count($aExtensions) > 0 && realpath($sPreviousVersionDir . '/extensions') != realpath(APPROOT . 'extensions')) { $aWritableDirs = array('extensions'); $aErrors = SetupUtils::CheckWritableDirs($aWritableDirs); if (count($aErrors) > 0) { $oPage->p("Cannot copy the extensions from '{$sPreviousVersionDir}/extensions' to '" . APPROOT . "extensions' due to the following access rights issue(s):"); foreach ($aErrors as $sDir => $oCheckResult) { $oPage->p('<img src="../images/error.png"/> ' . $oCheckResult->sLabel); } } else { $oPage->p("<b>Note:</b> The extensions present in '{$sPreviousVersionDir}/extensions' will be copied to '" . APPROOT . "extensions'."); $oPage->add('<input type="hidden" name="copy_extensions_from" value="' . htmlentities($sPreviousVersionDir . '/extensions', ENT_QUOTES, 'UTF-8') . '">'); } } } $oPage->add_ready_script(<<<EOF \t\$("#changes_summary .title").click(function() { \$(this).parent().toggleClass('closed'); } ); \t\$('input[name=upgrade_type]').bind('click change', function() { WizardUpdateButtons(); }); EOF ); $oMutex = new iTopMutex('cron.' . $this->oWizard->GetParameter('db_name', '') . '_' . $this->oWizard->GetParameter('db_prefix', ''), $this->oWizard->GetParameter('db_server', ''), $this->oWizard->GetParameter('db_user', ''), $this->oWizard->GetParameter('db_pwd', '')); if ($oMutex->TryLock()) { $oMutex->Unlock(); } else { $oPage->p("<img src=\"../images/error.png\"/> An iTop CRON process is being executed on the target database. It is highly recommended to stop any iTop CRON process prior to running the setup program."); } } }
$oP->add('<div style="max-height:400px; overflow: auto;">'); $oP->table($aConfig, array_reverse($aDetails)); $oP->add('</div>'); } else { $oP->p(Dict::S('bkp-status-backups-none')); } $oP->add("</fieldset>"); // Ongoing operation ? // $oBackupMutex = new iTopMutex('backup.' . utils::GetCurrentEnvironment()); if ($oBackupMutex->TryLock()) { $oBackupMutex->Unlock(); } else { $oP->p(Dict::S('bkp-backup-running')); } $oRestoreMutex = new iTopMutex('restore.' . utils::GetCurrentEnvironment()); if ($oRestoreMutex->TryLock()) { $oRestoreMutex->Unlock(); } else { $oP->p(Dict::S('bkp-restore-running')); } // Do backup now // $oBackupExec = new BackupExec(); $oNext = $oBackupExec->GetNextOccurrence(); $oP->p(Dict::Format('bkp-next-backup', $aWeekDayToString[$oNext->Format('N')], $oNext->Format('Y-m-d'), $oNext->Format('H:i'))); $oP->p('<button onclick="LaunchBackupNow();">' . Dict::S('bkp-button-backup-now') . '</button>'); $oP->add('<div id="backup_success" class="header_message message_ok" style="display: none;"></div>'); $oP->add('<div id="backup_errors" class="header_message message_error" style="display: none;"></div>'); $oP->add('<input type="hidden" name="restore_token" id="restore_token"/>'); $sConfirmBackup = addslashes(Dict::S('bkp-confirm-backup'));
/** * Checks if an exclusive lock exists on the specified DBObject. * @param string $sObjClass The class of the object for which to acquire the lock * @param integer $iObjKey The identifier of the object for which to acquire the lock * @return multitype:boolean iTopOwnershipLock Ambigous <boolean, string, DBObjectSet> */ public static function IsLocked($sObjClass, $iObjKey) { $bLocked = false; $oMutex = new iTopMutex('lock_' . $sObjClass . '::' . $iObjKey); $oMutex->Lock(); $oOwnershipLock = new iTopOwnershipLock($sObjClass, $iObjKey); if ($oOwnershipLock->IsOwned()) { $bLocked = true; } $oMutex->Unlock(); return array('locked' => $bLocked, 'owner' => $oOwnershipLock->GetOwner()); }