123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- <?php
- // Copyright (C) 2014 Combodo SARL
- //
- // This file is part of iTop.
- //
- // 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
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // iTop 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 Affero General Public License for more details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with iTop. If not, see <http://www.gnu.org/licenses/>
- /**
- * Monitor the backup
- *
- * @copyright Copyright (C) 2013 Combodo SARL
- * @license http://opensource.org/licenses/AGPL-3.0
- */
- if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
- require_once(__DIR__.'/../../approot.inc.php');
- require_once(APPROOT.'application/application.inc.php');
- require_once(APPROOT.'application/itopwebpage.class.inc.php');
- require_once(APPROOT.'application/startup.inc.php');
- require_once(APPROOT.'application/loginwebpage.class.inc.php');
- /////////////////////////////////////////////////////////////////////
- // Main program
- //
- LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be admin)
- //$sOperation = utils::ReadParam('operation', 'menu');
- //$oAppContext = new ApplicationContext();
- $oP = new iTopWebPage(Dict::S('bkp-status-title'));
- $oP->set_base(utils::GetAbsoluteUrlAppRoot().'pages/');
- try
- {
- $oP->add("<h1>".Dict::S('bkp-status-title')."</h1>");
- if (MetaModel::GetConfig()->Get('demo_mode'))
- {
- $oP->add("<div class=\"header_message message_info\">iTop is in <b>demonstration mode</b>: the feature is disabled.</div>");
- }
- $sImgOk = '<img src="../images/validation_ok.png"> ';
- $sImgError = '<img src="../images/validation_error.png"> ';
- $oP->add("<fieldset>");
- $oP->add("<legend>".Dict::S('bkp-status-checks')."</legend>");
- // Availability of mysqldump
- //
- $sMySQLBinDir = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', '');
- $sMySQLBinDir = utils::ReadParam('mysql_bindir', $sMySQLBinDir, true);
- if (empty($sMySQLBinDir))
- {
- $sMySQLDump = 'mysqldump';
- }
- else
- {
- //echo 'Info - Found mysql_bindir: '.$sMySQLBinDir;
- $sMySQLDump = '"'.$sMySQLBinDir.'/mysqldump"';
- }
- $sCommand = "$sMySQLDump -V 2>&1";
- $aOutput = array();
- $iRetCode = 0;
- exec($sCommand, $aOutput, $iRetCode);
- if ($iRetCode == 0)
- {
- $sMySqlDump = $sImgOk.Dict::Format("bkp-mysqldump-ok", $aOutput[0]);
- }
- elseif ($iRetCode == 1)
- {
- $sMySqlDump = $sImgError.Dict::Format("bkp-mysqldump-notfound", implode(' ', $aOutput));
- }
- else
- {
- $sMySqlDump = $sImgError.Dict::Format("bkp-mysqldump-issue", $iRetCode);
- }
- foreach($aOutput as $sLine)
- {
- //echo 'Info - mysqldump -V said: '.$sLine;
- }
- $oP->p($sMySqlDump);
- // Destination directory
- //
- // Make sure the target directory exists and is writeable
- $sBackupDir = APPROOT.'data/backups/';
- SetupUtils::builddir($sBackupDir);
- if (!is_dir($sBackupDir))
- {
- $oP->p($sImgError.Dict::Format('bkp-missing-dir', $sBackupDir));
- }
- else
- {
- $oP->p(Dict::Format('bkp-free-disk-space', SetupUtils::HumanReadableSize(SetupUtils::CheckDiskSpace($sBackupDir)), $sBackupDir));
- if (!is_writable($sBackupDir))
- {
- $oP->p($sImgError.Dict::Format('bkp-dir-not-writeable', $sBackupDir));
- }
- }
- $sBackupDirAuto = $sBackupDir.'auto/';
- SetupUtils::builddir($sBackupDirAuto);
- $sBackupDirManual = $sBackupDir.'manual/';
- SetupUtils::builddir($sBackupDirManual);
- // Wrong format
- //
- $sBackupFile = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'file_name_format', BACKUP_DEFAULT_FORMAT);
- $oBackup = new DBBackupScheduled();
- $sZipName = $oBackup->MakeName($sBackupFile);
- if ($sZipName == '')
- {
- $oP->p($sImgError.Dict::Format('bkp-wrong-format-spec', $sBackupFile, BACKUP_DEFAULT_FORMAT));
- }
- else
- {
- $oP->p(Dict::Format('bkp-name-sample', $sZipName));
- }
- // Week Days
- //
- $aWeekDayToString = array(
- 1 => Dict::S('DayOfWeek-Monday'),
- 2 => Dict::S('DayOfWeek-Tuesday'),
- 3 => Dict::S('DayOfWeek-Wednesday'),
- 4 => Dict::S('DayOfWeek-Thursday'),
- 5 => Dict::S('DayOfWeek-Friday'),
- 6 => Dict::S('DayOfWeek-Saturday'),
- 7 => Dict::S('DayOfWeek-Sunday')
- );
- $aDayLabels = array();
- $oBackupExec = new BackupExec();
- foreach ($oBackupExec->InterpretWeekDays() as $iDay)
- {
- $aDayLabels[] = $aWeekDayToString[$iDay];
- }
- $sDays = implode(', ', $aDayLabels);
- $sBackupTime = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'time', '23:30');
- $oP->p(Dict::Format('bkp-week-days', $sDays, $sBackupTime));
- $iRetention = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'retention_count', 5);
- $oP->p(Dict::Format('bkp-retention', $iRetention));
- $oP->add("</fieldset>");
- // List of backups
- //
- $aFiles = $oBackup->ListFiles($sBackupDirAuto);
- $aFilesToDelete = array();
- while (count($aFiles) > $iRetention - 1)
- {
- $aFilesToDelete[] = array_shift($aFiles);
- }
- $oRestoreMutex = new iTopMutex('restore.'.utils::GetCurrentEnvironment());
- if ($oRestoreMutex->TryLock())
- {
- $oRestoreMutex->Unlock();
- $sDisableRestore = '';
- }
- else
- {
- $sDisableRestore = 'disabled="disabled"';
- }
-
- // 1st table: list the backups made in the background
- //
- $aDetails = array();
- foreach ($oBackup->ListFiles($sBackupDirAuto) as $sBackupFile)
- {
- $sFileName = basename($sBackupFile);
- $sFilePath = 'auto/'.$sFileName;
- if (MetaModel::GetConfig()->Get('demo_mode'))
- {
- $sName = $sFileName;
- }
- else
- {
- $sAjax = utils::GetAbsoluteUrlModulePage('itop-backup', 'ajax.backup.php', array('operation' => 'download', 'file' => $sFilePath));
- $sName = "<a href=\"$sAjax\">".$sFileName.'</a>';
- }
- $sSize = SetupUtils::HumanReadableSize(filesize($sBackupFile));
- $sConfirmRestore = addslashes(Dict::Format('bkp-confirm-restore', $sFileName));
- $sFileEscaped = addslashes($sFilePath);
- $sRestoreBtn = '<button class="restore" onclick="LaunchRestoreNow(\''.$sFileEscaped.'\', \''.$sConfirmRestore.'\');" '.$sDisableRestore.'>'.Dict::S('bkp-button-restore-now').'</button>';
- if (in_array($sBackupFile, $aFilesToDelete))
- {
- $aDetails[] = array('file' => $sName.' <span class="next_to_delete" title="'.Dict::S('bkp-next-to-delete').'">*</span>', 'size' => $sSize, 'actions' => $sRestoreBtn);
- }
- else
- {
- $aDetails[] = array('file' => $sName, 'size' => $sSize, 'actions' => $sRestoreBtn);
- }
- }
- $aConfig = array(
- 'file' => array('label' => Dict::S('bkp-table-file'), 'description' => Dict::S('bkp-table-file+')),
- 'size' => array('label' => Dict::S('bkp-table-size'), 'description' => Dict::S('bkp-table-size+')),
- 'actions' => array('label' => Dict::S('bkp-table-actions'), 'description' => Dict::S('bkp-table-actions+')),
- );
- $oP->add("<fieldset>");
- $oP->add("<legend>".Dict::S('bkp-status-backups-auto')."</legend>");
- if (count($aDetails) > 0)
- {
- $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>");
- // 2nd table: list the backups made manually
- //
- $aDetails = array();
- foreach ($oBackup->ListFiles($sBackupDirManual) as $sBackupFile)
- {
- $sFileName = basename($sBackupFile);
- $sFilePath = 'manual/'.$sFileName;
- if (MetaModel::GetConfig()->Get('demo_mode'))
- {
- $sName = $sFileName;
- }
- else
- {
- $sAjax = utils::GetAbsoluteUrlModulePage('itop-backup', 'ajax.backup.php', array('operation' => 'download', 'file' => $sFilePath));
- $sName = "<a href=\"$sAjax\">".$sFileName.'</a>';
- }
- $sSize = SetupUtils::HumanReadableSize(filesize($sBackupFile));
- $sConfirmRestore = addslashes(Dict::Format('bkp-confirm-restore', $sFileName));
- $sFileEscaped = addslashes($sFilePath);
- $sRestoreBtn = '<button class="restore" onclick="LaunchRestoreNow(\''.$sFileEscaped.'\', \''.$sConfirmRestore.'\');" '.$sDisableRestore.'>'.Dict::S('bkp-button-restore-now').'</button>';
- $aDetails[] = array('file' => $sName, 'size' => $sSize, 'actions' => $sRestoreBtn);
- }
- $aConfig = array(
- 'file' => array('label' => Dict::S('bkp-table-file'), 'description' => Dict::S('bkp-table-file+')),
- 'size' => array('label' => Dict::S('bkp-table-size'), 'description' => Dict::S('bkp-table-size+')),
- 'actions' => array('label' => Dict::S('bkp-table-actions'), 'description' => Dict::S('bkp-table-actions+')),
- );
- $oP->add("<fieldset>");
- $oP->add("<legend>".Dict::S('bkp-status-backups-manual')."</legend>");
- if (count($aDetails) > 0)
- {
- $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'));
- $sPleaseWaitBackup = addslashes(Dict::S('bkp-wait-backup'));
- $sPleaseWaitRestore = addslashes(Dict::S('bkp-wait-restore'));
- $sRestoreDone = addslashes(Dict::S('bkp-success-restore'));
- $sMySQLBinDir = addslashes(MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', ''));
- $sDBHost = addslashes(MetaModel::GetConfig()->GetDBHost());
- $sDBUser = addslashes(MetaModel::GetConfig()->GetDBUser());
- $sDBPwd = addslashes(MetaModel::GetConfig()->GetDBPwd());
- $sDBName = addslashes(MetaModel::GetConfig()->GetDBName());
- $sDBSubName = addslashes(MetaModel::GetConfig()->GetDBSubName());
- $sEnvironment = addslashes(utils::GetCurrentEnvironment());
-
- $oP->add_script(
- <<<EOF
- function LaunchBackupNow()
- {
- $('#backup_success').hide();
- $('#backup_errors').hide();
- if (confirm('$sConfirmBackup'))
- {
- $.blockUI({ message: '<h1><img src="../images/indicator.gif" /> $sPleaseWaitBackup</h1>' });
- var oParams = {};
- oParams.operation = 'backup';
- $.post(GetAbsoluteUrlModulePage('itop-backup', 'ajax.backup.php'), oParams, function(data){
- if (data.search(/error|exceptio|notice|warning/i) != -1)
- {
- $('#backup_errors').html(data);
- $('#backup_errors').show();
- }
- else
- {
- window.location.reload();
- }
- $.unblockUI();
- });
- }
- }
- function LaunchRestoreNow(sBackupFile, sConfirmationMessage)
- {
- if (confirm(sConfirmationMessage))
- {
- $.blockUI({ message: '<h1><img src="../images/indicator.gif" /> $sPleaseWaitRestore</h1>' });
- $('#backup_success').hide();
- $('#backup_errors').hide();
- var oParams = {};
- oParams.operation = 'restore_get_token';
- oParams.file = sBackupFile;
- $.post(GetAbsoluteUrlModulePage('itop-backup', 'ajax.backup.php'), oParams, function(data){
- // Get the value of restore_token
- $('#backup_errors').append(data);
- var oParams = {};
- oParams.operation = 'restore_exec';
- oParams.token = $("#restore_token").val();
- oParams.mysql_bindir = '$sMySQLBinDir';
- oParams.db_host = '$sDBHost';
- oParams.db_user = '$sDBUser';
- oParams.db_pwd = '$sDBPwd';
- oParams.db_name = '$sDBName';
- oParams.db_subname = '$sDBSubName';
- oParams.environment = '$sEnvironment';
- if (oParams.token.length > 0)
- {
- $.post(GetAbsoluteUrlModulePage('itop-backup', 'ajax.backup.php'), oParams, function(data){
- if (data.search(/error|exceptio|notice|warning/i) != -1)
- {
- $('#backup_success').hide();
- $('#backup_errors').html(data);
- $('#backup_errors').show();
- }
- else
- {
- $('#backup_errors').hide();
- $('#backup_success').html('$sRestoreDone');
- $('#backup_success').show();
- }
- $.unblockUI();
- });
- }
- else
- {
- $('button.restore').attr('disabled', 'disabled');
- $.unblockUI();
- }
- });
- }
- }
- EOF
- );
- if (MetaModel::GetConfig()->Get('demo_mode'))
- {
- $oP->add_ready_script("$('button').attr('disabled', 'disabled').attr('title', 'Disabled in demonstration mode')");
- }
- }
- catch(Exception $e)
- {
- $oP->p('<b>'.$e->getMessage().'</b>');
- }
- $oP->output();
- ?>
|