mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-19 07:12:26 +02:00
Fix files using CrLf, convert them to Lf to have the whole repo using Lf
Warn your git config (core.autocrlf = input or true)
This commit is contained in:
@@ -1,203 +1,203 @@
|
||||
<?php
|
||||
// Copyright (C) 2014-2017 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/>
|
||||
|
||||
|
||||
class DBRestore extends DBBackup
|
||||
{
|
||||
/** @var string */
|
||||
private $sDBPwd;
|
||||
/** @var string */
|
||||
private $sDBUser;
|
||||
|
||||
public function __construct(\Config $oConfig = null)
|
||||
{
|
||||
parent::__construct($oConfig);
|
||||
|
||||
$this->sDBUser = $oConfig->Get('db_user');
|
||||
$this->sDBPwd = $oConfig->Get('db_pwd');
|
||||
}
|
||||
|
||||
protected function LogInfo($sMsg)
|
||||
{
|
||||
//IssueLog::Info('non juste info: '.$sMsg);
|
||||
}
|
||||
|
||||
protected function LogError($sMsg)
|
||||
{
|
||||
IssueLog::Error($sMsg);
|
||||
}
|
||||
|
||||
protected function LoadDatabase($sDataFile)
|
||||
{
|
||||
$this->LogInfo("Loading data onto $this->sDBHost/$this->sDBName(suffix:'$this->sDBSubName')");
|
||||
|
||||
// Just to check the connection to the DB (more accurate than getting the retcode of mysql)
|
||||
$oMysqli = $this->DBConnect();
|
||||
|
||||
$sHost = self::EscapeShellArg($this->sDBHost);
|
||||
$sUser = self::EscapeShellArg($this->sDBUser);
|
||||
$sPwd = self::EscapeShellArg($this->sDBPwd);
|
||||
$sDBName = self::EscapeShellArg($this->sDBName);
|
||||
if (empty($this->sMySQLBinDir))
|
||||
{
|
||||
$sMySQLExe = 'mysql';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sMySQLExe = '"'.$this->sMySQLBinDir.'/mysql"';
|
||||
}
|
||||
if (is_null($this->iDBPort))
|
||||
{
|
||||
$sPortOption = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sPortOption = '--port='.$this->iDBPort.' ';
|
||||
}
|
||||
|
||||
$sDataFileEscaped = self::EscapeShellArg($sDataFile);
|
||||
$sCommand = "$sMySQLExe --default-character-set=".DEFAULT_CHARACTER_SET." --host=$sHost $sPortOption --user=$sUser --password=$sPwd $sDBName <$sDataFileEscaped 2>&1";
|
||||
$sCommandDisplay = "$sMySQLExe --default-character-set=".DEFAULT_CHARACTER_SET." --host=$sHost $sPortOption --user=xxxx --password=xxxx $sDBName <$sDataFileEscaped 2>&1";
|
||||
|
||||
// Now run the command for real
|
||||
$this->LogInfo("Executing command: $sCommandDisplay");
|
||||
$aOutput = array();
|
||||
$iRetCode = 0;
|
||||
exec($sCommand, $aOutput, $iRetCode);
|
||||
foreach($aOutput as $sLine)
|
||||
{
|
||||
$this->LogInfo("mysql said: $sLine");
|
||||
}
|
||||
if ($iRetCode != 0)
|
||||
{
|
||||
$this->LogError("Failed to execute: $sCommandDisplay. The command returned:$iRetCode");
|
||||
foreach($aOutput as $sLine)
|
||||
{
|
||||
$this->LogError("mysql said: $sLine");
|
||||
}
|
||||
if (count($aOutput) == 1)
|
||||
{
|
||||
$sMoreInfo = trim($aOutput[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sMoreInfo = "Check the log file '".realpath(APPROOT.'/log/error.log')."' for more information.";
|
||||
}
|
||||
throw new BackupException("Failed to execute mysql: ".$sMoreInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use RestoreFromCompressedBackup instead
|
||||
*
|
||||
* @param $sZipFile
|
||||
* @param string $sEnvironment
|
||||
*/
|
||||
public function RestoreFromZip($sZipFile, $sEnvironment = 'production')
|
||||
{
|
||||
$this->RestoreFromCompressedBackup($sZipFile, $sEnvironment);
|
||||
}
|
||||
|
||||
/**
|
||||
* <strong>Warning</strong> : can't be called with a loaded DataModel as we're compiling after restore
|
||||
*
|
||||
* @param string $sFile A file with the extension .zip or .tar.gz
|
||||
* @param string $sEnvironment Target environment
|
||||
*
|
||||
* @throws \BackupException
|
||||
*
|
||||
* @uses \RunTimeEnvironment::CompileFrom()
|
||||
*/
|
||||
public function RestoreFromCompressedBackup($sFile, $sEnvironment = 'production')
|
||||
{
|
||||
$this->LogInfo("Starting restore of ".basename($sFile));
|
||||
|
||||
$sNormalizedFile = strtolower(basename($sFile));
|
||||
if (substr($sNormalizedFile, -4) == '.zip')
|
||||
{
|
||||
$this->LogInfo('zip file detected');
|
||||
$oArchive = new ZipArchiveEx();
|
||||
$oArchive->open($sFile);
|
||||
}
|
||||
elseif (substr($sNormalizedFile, -7) == '.tar.gz')
|
||||
{
|
||||
$this->LogInfo('tar.gz file detected');
|
||||
$oArchive = new TarGzArchive($sFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new BackupException('Unsupported format for a backup file: '.$sFile);
|
||||
}
|
||||
|
||||
// Load the database
|
||||
//
|
||||
$sDataDir = APPROOT.'data/tmp-backup-'.rand(10000, getrandmax());
|
||||
|
||||
SetupUtils::builddir($sDataDir); // Here is the directory
|
||||
$oArchive->extractTo($sDataDir);
|
||||
|
||||
$sDataFile = $sDataDir.'/itop-dump.sql';
|
||||
$this->LoadDatabase($sDataFile);
|
||||
|
||||
// Update the code
|
||||
//
|
||||
$sDeltaFile = APPROOT.'data/'.$sEnvironment.'.delta.xml';
|
||||
|
||||
if (is_file($sDataDir.'/delta.xml'))
|
||||
{
|
||||
// Extract and rename delta.xml => <env>.delta.xml;
|
||||
rename($sDataDir.'/delta.xml', $sDeltaFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
@unlink($sDeltaFile);
|
||||
}
|
||||
if (is_dir(APPROOT.'data/production-modules/'))
|
||||
{
|
||||
try
|
||||
{
|
||||
SetupUtils::rrmdir(APPROOT.'data/production-modules/');
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new BackupException("Can't remove production-modules dir", 0, $e);
|
||||
}
|
||||
}
|
||||
if (is_dir($sDataDir.'/production-modules'))
|
||||
{
|
||||
rename($sDataDir.'/production-modules', APPROOT.'data/production-modules/');
|
||||
}
|
||||
|
||||
$sConfigFile = APPROOT.'conf/'.$sEnvironment.'/config-itop.php';
|
||||
@chmod($sConfigFile, 0770); // Allow overwriting the file
|
||||
rename($sDataDir.'/config-itop.php', $sConfigFile);
|
||||
@chmod($sConfigFile, 0444); // Read-only
|
||||
|
||||
try
|
||||
{
|
||||
SetupUtils::rrmdir($sDataDir);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new BackupException("Can't remove data dir", 0, $e);
|
||||
}
|
||||
|
||||
$oEnvironment = new RunTimeEnvironment($sEnvironment);
|
||||
$oEnvironment->CompileFrom($sEnvironment);
|
||||
}
|
||||
}
|
||||
<?php
|
||||
// Copyright (C) 2014-2017 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/>
|
||||
|
||||
|
||||
class DBRestore extends DBBackup
|
||||
{
|
||||
/** @var string */
|
||||
private $sDBPwd;
|
||||
/** @var string */
|
||||
private $sDBUser;
|
||||
|
||||
public function __construct(\Config $oConfig = null)
|
||||
{
|
||||
parent::__construct($oConfig);
|
||||
|
||||
$this->sDBUser = $oConfig->Get('db_user');
|
||||
$this->sDBPwd = $oConfig->Get('db_pwd');
|
||||
}
|
||||
|
||||
protected function LogInfo($sMsg)
|
||||
{
|
||||
//IssueLog::Info('non juste info: '.$sMsg);
|
||||
}
|
||||
|
||||
protected function LogError($sMsg)
|
||||
{
|
||||
IssueLog::Error($sMsg);
|
||||
}
|
||||
|
||||
protected function LoadDatabase($sDataFile)
|
||||
{
|
||||
$this->LogInfo("Loading data onto $this->sDBHost/$this->sDBName(suffix:'$this->sDBSubName')");
|
||||
|
||||
// Just to check the connection to the DB (more accurate than getting the retcode of mysql)
|
||||
$oMysqli = $this->DBConnect();
|
||||
|
||||
$sHost = self::EscapeShellArg($this->sDBHost);
|
||||
$sUser = self::EscapeShellArg($this->sDBUser);
|
||||
$sPwd = self::EscapeShellArg($this->sDBPwd);
|
||||
$sDBName = self::EscapeShellArg($this->sDBName);
|
||||
if (empty($this->sMySQLBinDir))
|
||||
{
|
||||
$sMySQLExe = 'mysql';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sMySQLExe = '"'.$this->sMySQLBinDir.'/mysql"';
|
||||
}
|
||||
if (is_null($this->iDBPort))
|
||||
{
|
||||
$sPortOption = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sPortOption = '--port='.$this->iDBPort.' ';
|
||||
}
|
||||
|
||||
$sDataFileEscaped = self::EscapeShellArg($sDataFile);
|
||||
$sCommand = "$sMySQLExe --default-character-set=".DEFAULT_CHARACTER_SET." --host=$sHost $sPortOption --user=$sUser --password=$sPwd $sDBName <$sDataFileEscaped 2>&1";
|
||||
$sCommandDisplay = "$sMySQLExe --default-character-set=".DEFAULT_CHARACTER_SET." --host=$sHost $sPortOption --user=xxxx --password=xxxx $sDBName <$sDataFileEscaped 2>&1";
|
||||
|
||||
// Now run the command for real
|
||||
$this->LogInfo("Executing command: $sCommandDisplay");
|
||||
$aOutput = array();
|
||||
$iRetCode = 0;
|
||||
exec($sCommand, $aOutput, $iRetCode);
|
||||
foreach($aOutput as $sLine)
|
||||
{
|
||||
$this->LogInfo("mysql said: $sLine");
|
||||
}
|
||||
if ($iRetCode != 0)
|
||||
{
|
||||
$this->LogError("Failed to execute: $sCommandDisplay. The command returned:$iRetCode");
|
||||
foreach($aOutput as $sLine)
|
||||
{
|
||||
$this->LogError("mysql said: $sLine");
|
||||
}
|
||||
if (count($aOutput) == 1)
|
||||
{
|
||||
$sMoreInfo = trim($aOutput[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sMoreInfo = "Check the log file '".realpath(APPROOT.'/log/error.log')."' for more information.";
|
||||
}
|
||||
throw new BackupException("Failed to execute mysql: ".$sMoreInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use RestoreFromCompressedBackup instead
|
||||
*
|
||||
* @param $sZipFile
|
||||
* @param string $sEnvironment
|
||||
*/
|
||||
public function RestoreFromZip($sZipFile, $sEnvironment = 'production')
|
||||
{
|
||||
$this->RestoreFromCompressedBackup($sZipFile, $sEnvironment);
|
||||
}
|
||||
|
||||
/**
|
||||
* <strong>Warning</strong> : can't be called with a loaded DataModel as we're compiling after restore
|
||||
*
|
||||
* @param string $sFile A file with the extension .zip or .tar.gz
|
||||
* @param string $sEnvironment Target environment
|
||||
*
|
||||
* @throws \BackupException
|
||||
*
|
||||
* @uses \RunTimeEnvironment::CompileFrom()
|
||||
*/
|
||||
public function RestoreFromCompressedBackup($sFile, $sEnvironment = 'production')
|
||||
{
|
||||
$this->LogInfo("Starting restore of ".basename($sFile));
|
||||
|
||||
$sNormalizedFile = strtolower(basename($sFile));
|
||||
if (substr($sNormalizedFile, -4) == '.zip')
|
||||
{
|
||||
$this->LogInfo('zip file detected');
|
||||
$oArchive = new ZipArchiveEx();
|
||||
$oArchive->open($sFile);
|
||||
}
|
||||
elseif (substr($sNormalizedFile, -7) == '.tar.gz')
|
||||
{
|
||||
$this->LogInfo('tar.gz file detected');
|
||||
$oArchive = new TarGzArchive($sFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new BackupException('Unsupported format for a backup file: '.$sFile);
|
||||
}
|
||||
|
||||
// Load the database
|
||||
//
|
||||
$sDataDir = APPROOT.'data/tmp-backup-'.rand(10000, getrandmax());
|
||||
|
||||
SetupUtils::builddir($sDataDir); // Here is the directory
|
||||
$oArchive->extractTo($sDataDir);
|
||||
|
||||
$sDataFile = $sDataDir.'/itop-dump.sql';
|
||||
$this->LoadDatabase($sDataFile);
|
||||
|
||||
// Update the code
|
||||
//
|
||||
$sDeltaFile = APPROOT.'data/'.$sEnvironment.'.delta.xml';
|
||||
|
||||
if (is_file($sDataDir.'/delta.xml'))
|
||||
{
|
||||
// Extract and rename delta.xml => <env>.delta.xml;
|
||||
rename($sDataDir.'/delta.xml', $sDeltaFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
@unlink($sDeltaFile);
|
||||
}
|
||||
if (is_dir(APPROOT.'data/production-modules/'))
|
||||
{
|
||||
try
|
||||
{
|
||||
SetupUtils::rrmdir(APPROOT.'data/production-modules/');
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new BackupException("Can't remove production-modules dir", 0, $e);
|
||||
}
|
||||
}
|
||||
if (is_dir($sDataDir.'/production-modules'))
|
||||
{
|
||||
rename($sDataDir.'/production-modules', APPROOT.'data/production-modules/');
|
||||
}
|
||||
|
||||
$sConfigFile = APPROOT.'conf/'.$sEnvironment.'/config-itop.php';
|
||||
@chmod($sConfigFile, 0770); // Allow overwriting the file
|
||||
rename($sDataDir.'/config-itop.php', $sConfigFile);
|
||||
@chmod($sConfigFile, 0444); // Read-only
|
||||
|
||||
try
|
||||
{
|
||||
SetupUtils::rrmdir($sDataDir);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new BackupException("Can't remove data dir", 0, $e);
|
||||
}
|
||||
|
||||
$oEnvironment = new RunTimeEnvironment($sEnvironment);
|
||||
$oEnvironment->CompileFrom($sEnvironment);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,58 +1,58 @@
|
||||
<?php
|
||||
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-backup/2.5.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Backup utilities',
|
||||
'category' => 'Application management',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => array(
|
||||
),
|
||||
'mandatory' => true,
|
||||
'visible' => false,
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => array(
|
||||
'main.itop-backup.php',
|
||||
'model.itop-backup.php',
|
||||
),
|
||||
'webservice' => array(
|
||||
//'webservices.itop-backup.php',
|
||||
),
|
||||
'dictionary' => array(
|
||||
'en.dict.itop-backup.php',
|
||||
'fr.dict.itop-backup.php',
|
||||
//'de.dict.itop-backup.php',
|
||||
),
|
||||
'data.struct' => array(
|
||||
//'data.struct.itop-backup.xml',
|
||||
),
|
||||
'data.sample' => array(
|
||||
//'data.sample.itop-backup.xml',
|
||||
),
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => '',
|
||||
'doc.more_information' => '',
|
||||
|
||||
// Default settings
|
||||
//
|
||||
'settings' => array(
|
||||
'mysql_bindir' => '',
|
||||
'week_days' => 'monday, tuesday, wednesday, thursday, friday',
|
||||
'time' => '23:30',
|
||||
//'file_name_format' => '__DB__-%Y-%m-%d_%H_%M',
|
||||
'retention_count' => 5,
|
||||
'enabled' => true,
|
||||
'debug' => false
|
||||
),
|
||||
)
|
||||
);
|
||||
<?php
|
||||
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-backup/2.5.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Backup utilities',
|
||||
'category' => 'Application management',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => array(
|
||||
),
|
||||
'mandatory' => true,
|
||||
'visible' => false,
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => array(
|
||||
'main.itop-backup.php',
|
||||
'model.itop-backup.php',
|
||||
),
|
||||
'webservice' => array(
|
||||
//'webservices.itop-backup.php',
|
||||
),
|
||||
'dictionary' => array(
|
||||
'en.dict.itop-backup.php',
|
||||
'fr.dict.itop-backup.php',
|
||||
//'de.dict.itop-backup.php',
|
||||
),
|
||||
'data.struct' => array(
|
||||
//'data.struct.itop-backup.xml',
|
||||
),
|
||||
'data.sample' => array(
|
||||
//'data.sample.itop-backup.xml',
|
||||
),
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => '',
|
||||
'doc.more_information' => '',
|
||||
|
||||
// Default settings
|
||||
//
|
||||
'settings' => array(
|
||||
'mysql_bindir' => '',
|
||||
'week_days' => 'monday, tuesday, wednesday, thursday, friday',
|
||||
'time' => '23:30',
|
||||
//'file_name_format' => '__DB__-%Y-%m-%d_%H_%M',
|
||||
'retention_count' => 5,
|
||||
'enabled' => true,
|
||||
'debug' => false
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
@@ -1,398 +1,398 @@
|
||||
<?php
|
||||
// Copyright (C) 2016-2018 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) 2016-2018 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
|
||||
if (!defined('APPROOT')) 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(); // Check user rights and prompt if needed
|
||||
ApplicationMenu::CheckMenuIdEnabled('BackupStatus');
|
||||
|
||||
//$sOperation = utils::ReadParam('operation', 'menu');
|
||||
//$oAppContext = new ApplicationContext();
|
||||
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
$oP = new iTopWebPage(Dict::S('bkp-status-title'));
|
||||
$oP->set_base(utils::GetAbsoluteUrlAppRoot().'pages/');
|
||||
|
||||
$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)
|
||||
{
|
||||
IssueLog::Info("$sCommand 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->IsLocked())
|
||||
{
|
||||
$sDisableRestore = 'disabled="disabled"';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sDisableRestore = '';
|
||||
}
|
||||
|
||||
// 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->IsLocked())
|
||||
{
|
||||
$oP->p(Dict::S('bkp-backup-running'));
|
||||
}
|
||||
$oRestoreMutex = new iTopMutex('restore.'.utils::GetCurrentEnvironment());
|
||||
if ($oRestoreMutex->IsLocked())
|
||||
{
|
||||
$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()->Get('db_host'));
|
||||
$sDBUser = addslashes(MetaModel::GetConfig()->Get('db_user'));
|
||||
$sDBPwd = addslashes(MetaModel::GetConfig()->Get('db_pwd'));
|
||||
$sDBName = addslashes(MetaModel::GetConfig()->Get('db_name'));
|
||||
$sDBSubName = addslashes(MetaModel::GetConfig()->Get('db_subname'));
|
||||
|
||||
$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(); // token to check auth + rights without loading MetaModel
|
||||
oParams.environment = '$sEnvironment'; // needed to load the config
|
||||
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').prop('disabled', true);
|
||||
$.unblockUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
EOF
|
||||
);
|
||||
|
||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
$oP->add_ready_script("$('button').prop('disabled', true).attr('title', 'Disabled in demonstration mode')");
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$oP = new iTopWebPage(Dict::S('bkp-status-title'));
|
||||
$oP->p('<b>'.$e->getMessage().'</b>');
|
||||
}
|
||||
|
||||
$oP->output();
|
||||
?>
|
||||
<?php
|
||||
// Copyright (C) 2016-2018 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) 2016-2018 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
|
||||
if (!defined('APPROOT')) 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(); // Check user rights and prompt if needed
|
||||
ApplicationMenu::CheckMenuIdEnabled('BackupStatus');
|
||||
|
||||
//$sOperation = utils::ReadParam('operation', 'menu');
|
||||
//$oAppContext = new ApplicationContext();
|
||||
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
$oP = new iTopWebPage(Dict::S('bkp-status-title'));
|
||||
$oP->set_base(utils::GetAbsoluteUrlAppRoot().'pages/');
|
||||
|
||||
$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)
|
||||
{
|
||||
IssueLog::Info("$sCommand 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->IsLocked())
|
||||
{
|
||||
$sDisableRestore = 'disabled="disabled"';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sDisableRestore = '';
|
||||
}
|
||||
|
||||
// 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->IsLocked())
|
||||
{
|
||||
$oP->p(Dict::S('bkp-backup-running'));
|
||||
}
|
||||
$oRestoreMutex = new iTopMutex('restore.'.utils::GetCurrentEnvironment());
|
||||
if ($oRestoreMutex->IsLocked())
|
||||
{
|
||||
$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()->Get('db_host'));
|
||||
$sDBUser = addslashes(MetaModel::GetConfig()->Get('db_user'));
|
||||
$sDBPwd = addslashes(MetaModel::GetConfig()->Get('db_pwd'));
|
||||
$sDBName = addslashes(MetaModel::GetConfig()->Get('db_name'));
|
||||
$sDBSubName = addslashes(MetaModel::GetConfig()->Get('db_subname'));
|
||||
|
||||
$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(); // token to check auth + rights without loading MetaModel
|
||||
oParams.environment = '$sEnvironment'; // needed to load the config
|
||||
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').prop('disabled', true);
|
||||
$.unblockUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
EOF
|
||||
);
|
||||
|
||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
$oP->add_ready_script("$('button').prop('disabled', true).attr('title', 'Disabled in demonstration mode')");
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$oP = new iTopWebPage(Dict::S('bkp-status-title'));
|
||||
$oP->p('<b>'.$e->getMessage().'</b>');
|
||||
}
|
||||
|
||||
$oP->output();
|
||||
?>
|
||||
|
||||
Reference in New Issue
Block a user