mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-20 07:42:17 +02:00
The Hub Connects !!
Adding iTop Hub Connector. SVN:trunk[5270]
This commit is contained in:
362
datamodels/2.x/itop-hub-connector/ajax.php
Normal file
362
datamodels/2.x/itop-hub-connector/ajax.php
Normal file
@@ -0,0 +1,362 @@
|
||||
<?php
|
||||
// Copyright (C) 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/>
|
||||
|
||||
/**
|
||||
* Handles various ajax requests - called through pages/exec.php
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2017 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
if (!defined('__DIR__'))
|
||||
define('__DIR__', dirname(__FILE__));
|
||||
require_once (APPROOT.'application/webpage.class.inc.php');
|
||||
require_once (APPROOT.'application/ajaxwebpage.class.inc.php');
|
||||
require_once (APPROOT.'application/utils.inc.php');
|
||||
require_once (APPROOT.'core/log.class.inc.php');
|
||||
IssueLog::Enable(APPROOT.'log/error.log');
|
||||
|
||||
require_once (APPROOT.'setup/runtimeenv.class.inc.php');
|
||||
require_once (APPROOT.'setup/backup.class.inc.php');
|
||||
require_once (APPROOT.'core/mutex.class.inc.php');
|
||||
require_once (APPROOT.'core/dict.class.inc.php');
|
||||
require_once (__DIR__.'/hubruntimeenvironment.class.inc.php');
|
||||
|
||||
/**
|
||||
* Overload of DBBackup to handle logging
|
||||
*/
|
||||
class DBBackupWithErrorReporting extends DBBackup
|
||||
{
|
||||
|
||||
protected $aInfos = array();
|
||||
|
||||
protected $aErrors = array();
|
||||
|
||||
protected function LogInfo($sMsg)
|
||||
{
|
||||
$aInfos[] = $sMsg;
|
||||
}
|
||||
|
||||
protected function LogError($sMsg)
|
||||
{
|
||||
IssueLog::Error($sMsg);
|
||||
$aErrors[] = $sMsg;
|
||||
}
|
||||
|
||||
public function GetInfos()
|
||||
{
|
||||
return $this->aInfos;
|
||||
}
|
||||
|
||||
public function GetErrors()
|
||||
{
|
||||
return $this->aErrors;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $sTargetFile
|
||||
* @throws Exception
|
||||
* @return DBBackupWithErrorReporting
|
||||
*/
|
||||
function DoBackup($sTargetFile)
|
||||
{
|
||||
// Make sure the target directory exists
|
||||
$sBackupDir = dirname($sTargetFile);
|
||||
SetupUtils::builddir($sBackupDir);
|
||||
|
||||
$oBackup = new DBBackupWithErrorReporting();
|
||||
$oBackup->SetMySQLBinDir(MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', ''));
|
||||
$sSourceConfigFile = APPCONF.utils::GetCurrentEnvironment().'/'.ITOP_CONFIG_FILE;
|
||||
|
||||
$oMutex = new iTopMutex('backup.'.utils::GetCurrentEnvironment());
|
||||
$oMutex->Lock();
|
||||
try
|
||||
{
|
||||
$oBackup->CreateCompressedBackup($sTargetFile, $sSourceConfigFile);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$oMutex->Unlock();
|
||||
throw $e;
|
||||
}
|
||||
$oMutex->Unlock();
|
||||
return $oBackup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the status of the current ajax execution (as a JSON structure)
|
||||
*
|
||||
* @param string $sMessage
|
||||
* @param bool $bSuccess
|
||||
* @param number $iErrorCode
|
||||
* @param array $aMoreFields
|
||||
* Extra fields to pass to the caller, if needed
|
||||
*/
|
||||
function ReportStatus($sMessage, $bSuccess, $iErrorCode = 0, $aMoreFields = array())
|
||||
{
|
||||
$oPage = new ajax_page("");
|
||||
$oPage->no_cache();
|
||||
$oPage->SetContentType('application/json');
|
||||
$aResult = array(
|
||||
'code' => $iErrorCode,
|
||||
'message' => $sMessage,
|
||||
'fields' => $aMoreFields
|
||||
);
|
||||
$oPage->add(json_encode($aResult));
|
||||
$oPage->output();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to output the status of a successful execution
|
||||
*
|
||||
* @param string $sMessage
|
||||
* @param array $aMoreFields
|
||||
* Extra fields to pass to the caller, if needed
|
||||
*/
|
||||
function ReportSuccess($sMessage, $aMoreFields = array())
|
||||
{
|
||||
ReportStatus($sMessage, true, 0, $aMoreFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to output the status of a failed execution
|
||||
*
|
||||
* @param string $sMessage
|
||||
* @param number $iErrorCode
|
||||
* @param array $aMoreFields
|
||||
* Extra fields to pass to the caller, if needed
|
||||
*/
|
||||
function ReportError($sMessage, $iErrorCode, $aMoreFields = array())
|
||||
{
|
||||
if ($iErrorCode==0)
|
||||
{
|
||||
// 0 means no error, so change it if no meaningful error code is supplied
|
||||
$iErrorCode = -1;
|
||||
}
|
||||
ReportStatus($sMessage, false, $iErrorCode, $aMoreFields);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
utils::PushArchiveMode(false);
|
||||
|
||||
ini_set('max_execution_time', max(3600, ini_get('max_execution_time'))); // Under Windows SQL/backup operations are part of the PHP timeout and require extra time
|
||||
ini_set('display_errors', 1); // Make sure that fatal errors remain visible from the end-user
|
||||
|
||||
// Most of the ajax calls are done without the MetaModel being loaded
|
||||
// Therefore, the language must be passed as an argument,
|
||||
// and the dictionnaries be loaded here
|
||||
$sLanguage = utils::ReadParam('language', '');
|
||||
if ($sLanguage!='')
|
||||
{
|
||||
foreach (glob(APPROOT.'env-production/dictionaries/*.dict.php') as $sFilePath)
|
||||
{
|
||||
require_once ($sFilePath);
|
||||
}
|
||||
|
||||
$aLanguages = Dict::GetLanguages();
|
||||
if (array_key_exists($sLanguage, $aLanguages))
|
||||
{
|
||||
Dict::SetUserLanguage($sLanguage);
|
||||
}
|
||||
}
|
||||
$sOperation = utils::ReadParam('operation', '');
|
||||
switch ($sOperation)
|
||||
{
|
||||
case 'check_before_backup':
|
||||
require_once (APPROOT.'/application/startup.inc.php');
|
||||
require_once (APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be admin)
|
||||
|
||||
$sDBBackupPath = APPROOT.'data/backups/manual';
|
||||
$aChecks = SetupUtils::CheckBackupPrerequisites($sDBBackupPath);
|
||||
$bFailed = false;
|
||||
foreach ($aChecks as $oCheckResult)
|
||||
{
|
||||
if ($oCheckResult->iSeverity==CheckResult::ERROR)
|
||||
{
|
||||
$bFailed = true;
|
||||
ReportError($oCheckResult->sLabel, -2);
|
||||
}
|
||||
}
|
||||
if (!$bFailed)
|
||||
{
|
||||
// Continue the checks
|
||||
$fFreeSpace = SetupUtils::CheckDiskSpace($sDBBackupPath);
|
||||
if ($fFreeSpace!==false)
|
||||
{
|
||||
$sMessage = Dict::Format('iTopHub:BackupFreeDiskSpaceIn', SetupUtils::HumanReadableSize($fFreeSpace), dirname($sDBBackupPath));
|
||||
ReportSuccess($sMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportError(Dict::S('iTopHub:FailedToCheckFreeDiskSpace'), -1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'do_backup':
|
||||
require_once (APPROOT.'/application/startup.inc.php');
|
||||
require_once (APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be admin)
|
||||
|
||||
try
|
||||
{
|
||||
set_time_limit(0);
|
||||
$sBackupPath = APPROOT.'/data/backups/manual/backup-';
|
||||
$iSuffix = 1;
|
||||
$sSuffix = '';
|
||||
// Generate a unique name...
|
||||
do
|
||||
{
|
||||
$sBackupFile = $sBackupPath.date('Y-m-d-His').$sSuffix;
|
||||
$sSuffix = '-'.$iSuffix;
|
||||
$iSuffix++ ;
|
||||
}
|
||||
while (file_exists($sBackupFile));
|
||||
|
||||
$oBackup = DoBackup($sBackupFile);
|
||||
$aErrors = $oBackup->GetErrors();
|
||||
if (count($aErrors)>0)
|
||||
{
|
||||
ReportError(Dict::S('iTopHub:BackupFailed'), -1, $aErrors);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportSuccess(Dict::S('iTopHub:BackupOk'));
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
ReportError($e->getMessage(), $e->getCode());
|
||||
}
|
||||
break;
|
||||
|
||||
case 'compile':
|
||||
// First step: prepare the datamodel, if it fails, roll-back
|
||||
$aSelectedExtensionCodes = utils::ReadParam('extension_codes', array());
|
||||
$aSelectedExtensionDirs = utils::ReadParam('extension_dirs', array());
|
||||
|
||||
$oRuntimeEnv = new HubRunTimeEnvironment('production', false); // use a temp environment: production-build
|
||||
$oRuntimeEnv->MoveSelectedExtensions(APPROOT.'/data/downloaded-extensions/', $aSelectedExtensionDirs);
|
||||
|
||||
$oConfig = new Config(APPCONF.'production/'.ITOP_CONFIG_FILE);
|
||||
|
||||
$aSelectModules = $oRuntimeEnv->CompileFrom('production', false); // WARNING symlinks does not seem to be compatible with manual Commit
|
||||
|
||||
$oRuntimeEnv->UpdateIncludes($oConfig);
|
||||
|
||||
$oRuntimeEnv->InitDataModel($oConfig, true /* model only */);
|
||||
|
||||
$oRuntimeEnv->CheckMetaModel(); // Will throw an exception if a problem is detected
|
||||
|
||||
// Everything seems Ok so far, commit in env-production!
|
||||
$oRuntimeEnv->WriteConfigFileSafe($oConfig);
|
||||
$oRuntimeEnv->Commit();
|
||||
|
||||
// Report the success in a way that will be detected by the ajax caller
|
||||
ReportSuccess('Ok'); // No access to Dict::S here
|
||||
break;
|
||||
|
||||
case 'move_to_production':
|
||||
// Second step: update the schema and the data
|
||||
// Everything happening below is based on env-production
|
||||
$oRuntimeEnv = new RunTimeEnvironment('production', true);
|
||||
|
||||
try
|
||||
{
|
||||
// Load the "production" config file to clone & update it
|
||||
$oConfig = new Config(APPCONF.'production/'.ITOP_CONFIG_FILE);
|
||||
|
||||
$oRuntimeEnv->InitDataModel($oConfig, true /* model only */);
|
||||
|
||||
$aAvailableModules = $oRuntimeEnv->AnalyzeInstallation($oConfig, $oRuntimeEnv->GetBuildDir(), true);
|
||||
|
||||
$aSelectedModules = array();
|
||||
foreach ($aAvailableModules as $sModuleId => $aModule)
|
||||
{
|
||||
if (($sModuleId==ROOT_MODULE)||($sModuleId==DATAMODEL_MODULE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aSelectedModules[] = $sModuleId;
|
||||
}
|
||||
}
|
||||
|
||||
$oRuntimeEnv->CallInstallerHandlers($aAvailableModules, $aSelectedModules, 'BeforeDatabaseCreation');
|
||||
|
||||
// Now I assume that there is a DB for this environment...
|
||||
$oRuntimeEnv->CreateDatabaseStructure($oConfig, 'upgrade');
|
||||
|
||||
$oRuntimeEnv->CallInstallerHandlers($aAvailableModules, $aSelectedModules, 'AfterDatabaseCreation');
|
||||
|
||||
$oRuntimeEnv->UpdatePredefinedObjects();
|
||||
|
||||
$oRuntimeEnv->CallInstallerHandlers($aAvailableModules, $aSelectedModules, 'AfterDatabaseSetup');
|
||||
|
||||
// Record the installation so that the "about box" knows about the installed modules
|
||||
$sDataModelVersion = $oRuntimeEnv->GetCurrentDataModelVersion();
|
||||
|
||||
$oExtensionsMap = new iTopExtensionsMap();
|
||||
|
||||
// Default choices = as before
|
||||
$oExtensionsMap->LoadChoicesFromDatabase($oConfig);
|
||||
foreach ($oExtensionsMap->GetAllExtensions() as $oExtension)
|
||||
{
|
||||
// Plus all "remote" extensions
|
||||
if ($oExtension->sSource==iTopExtension::SOURCE_REMOTE)
|
||||
{
|
||||
$oExtensionsMap->MarkAsChosen($oExtension->sCode);
|
||||
}
|
||||
}
|
||||
$aSelectedExtensionCodes = array();
|
||||
foreach ($oExtensionsMap->GetChoices() as $oExtension)
|
||||
{
|
||||
$aSelectedExtensionCodes[] = $oExtension->sCode;
|
||||
}
|
||||
$aSelectedExtensions = $oExtensionsMap->GetChoices();
|
||||
$oRuntimeEnv->RecordInstallation($oConfig, $sDataModelVersion, $aSelectedModules, $aSelectedExtensionCodes, 'Done by the iTop Hub Connector');
|
||||
|
||||
// Report the success in a way that will be detected by the ajax caller
|
||||
ReportSuccess(Dict::S('iTopHub:CompiledOK'));
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Note: at this point, the dictionnary is not necessarily loaded
|
||||
IssueLog::Error(get_class($e).': '.Dict::S('iTopHub:ConfigurationSafelyReverted')."\n".$e->getMessage());
|
||||
IssueLog::Error('Debug trace: '.$e->getTraceAsString());
|
||||
ReportError($e->getMessage(), $e->getCode());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ReportError("Invalid operation: '$sOperation'", -1);
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
IssueLog::Error(get_class($e).': '.Dict::S('iTopHub:ConfigurationSafelyReverted')."\n".$e->getMessage());
|
||||
IssueLog::Error('Debug trace: '.$e->getTraceAsString());
|
||||
|
||||
utils::PopArchiveMode();
|
||||
|
||||
ReportError($e->getMessage(), $e->getCode());
|
||||
}
|
||||
Reference in New Issue
Block a user