Commit f2124f23 authored by Marius Burkard's avatar Marius Burkard

- added some logging

parent 02e3ef60
......@@ -13,19 +13,24 @@ class addon_installer {
$ret = null;
$retval = 0;
$app->log('Extracting addon package ' . $package_file, 0, false);
$cmd = 'which unzip';
$tmp = explode("\n", exec($cmd, $ret, $retval));
if($retval != 0) {
$app->log('The unzip command was not found on the server.', 2, false);
throw new AddonInstallerException('unzip tool not found.');
}
$unzip = reset($tmp);
unset($tmp);
if(!$unzip) {
$app->log('Unzip tool was not found.', 2, false);
throw new AddonInstallerException('unzip tool not found.');
}
$temp_dir = $app->system->tempdir(sys_get_temp_dir(), 'addon_', 0700);
if(!$temp_dir) {
$app->log('Could not create the temp dir.', 2, false);
throw new AddonInstallerException('Could not create temp dir.');
}
......@@ -34,9 +39,12 @@ class addon_installer {
$cmd = $unzip . ' -d ' . escapeshellarg($temp_dir) . ' ' . escapeshellarg($package_file);
exec($cmd, $ret, $retval);
if($retval != 0) {
$app->log('Package extraction failed.', 2, false);
throw new AddonInstallerException('Package extraction failed.');
}
$app->log('Extracted to ' . $temp_dir, 0, false);
return $temp_dir;
}
......@@ -46,36 +54,48 @@ class addon_installer {
* @throws AddonInstallerValidationException
*/
private function validatePackage($path) {
$app->log('Validating extracted addon at ' . $path, 0, false);
if(!is_dir($path)) {
$app->log('Invalid path.', 2, false);
throw new AddonInstallerValidationException('Invalid path.');
}
$ini_file = $path . '/addon.ini';
if(!is_file($ini_file)) {
$app->log('Addon ini file missing.', 2, false);
throw new AddonInstallerValidationException('Addon ini file missing.');
}
$app->log('Parsing ini ' . $ini_file, 0, false);
$ini = parse_ini_file($ini_file, true);
if(!$ini || !isset($ini['addon'])) {
$app->log('Ini file could not be read.', 2, false);
throw new AddonInstallerValidationException('Ini file is missing addon section.');
}
$addon = $ini['addon'];
if(!isset($addon['ident']) || !isset($addon['name']) || !isset($addon['version'])) {
$app->log('Addon data in ini file missing or invalid.', 2, false);
throw new AddonInstallerValidationException('Ini file is missing addon ident/name/version.');
}
$class_file = $path . '/' . $addon['ident'] . '.addon.php';
if(!is_file($class_file)) {
$app->log('Base class file in addon not found', 2, false);
throw new AddonInstallerValidationException('Package is missing main addon class.');
}
if(isset($ini['ispconfig']['version.min']) && $ini['ispconfig']['version.min'] && version_compare($ini['ispconfig']['version.min'], ISPC_APP_VERSION, '>')) {
$app->log('ISPConfig version too low for this addon.', 2, false);
throw new AddonInstallerValidationException('Addon requires at least ISPConfig version ' . $ini['ispconfig']['version.min'] . '.');
} elseif(isset($ini['ispconfig']['version.max']) && $ini['ispconfig']['version.max'] && version_compare($ini['ispconfig']['version.min'], ISPC_APP_VERSION, '<')) {
$app->log('ISPConfig version too high for this addon.', 2, false);
throw new AddonInstallerValidationException('Addon allows at max ISPConfig version ' . $ini['ispconfig']['version.max'] . '.');
}
$app->log('Loaded addon installer ' . $class_file, 0, false);
$addon['class_file'] = $class_file;
$addon['class_name'] = substr(basename($class_file), 0, -10) . '_addon_installer';
......@@ -92,21 +112,30 @@ class addon_installer {
// check for previous version
if(is_dir($addon_path . '/' . $ident) && is_file($addon_path . '/' . $ident . '/addon.ini')) {
$addon = parse_ini_file($addon_path . '/' . $ident . '/addon.ini', true);
if($addon && isset($addon['addon'])) {
$addon = $addon['addon']; // ini section
} else {
$addon = false;
}
if(!$addon || !isset($addon['version']) || !isset($addon['ident']) || $addon['ident'] != $ident) {
throw new AddonInstallerException('Installed app found but it is invalid.');
$app->log('Could not get version of installed addon.', 2, false);
throw new AddonInstallerException('Installed app ' . $ident . ' found but it is invalid.');
}
$file_version = $addon['version'];
$app->log('Installed version of addon ' . $ident . ' is ' . $file_version, 0, false);
}
$check = $app->db->queryOneRecord('SELECT `addon_version` FROM `addons` WHERE `addon_ident` = ?', $ident);
if($check && $check['addon_version']) {
$db_version = $check['addon_version'];
$app->log('Installed version of addon ' . $ident . ' (in db) is ' . $db_version . '.', 0, false);
}
if(!$file_version && !$db_version) {
return false;
} elseif($file_version != $db_version) {
$app->log('Version mismatch between ini file and database (' . $file_version . ' != ' . $db_version . ').', 0, false);
throw new AddonInstallerException('Addon version mismatch in database (' . $db_version . ') and file system (' . $file_version . ').');
}
......@@ -126,14 +155,17 @@ class addon_installer {
$app->load('ispconfig_addon_installer_base');
if(!is_file($package_file)) {
$app->log('Package file not found: ' . $package_file, 2, false);
throw new AddonInstallerException('Package file not found.');
} elseif(substr($package_file, -4) !== '.pkg') {
$app->log('Invalid package file: ' . $package_file, 2, false);
throw new AddonInstallerException('Invalid package file.');
}
$tmp_dir = $this->extractPackage($package_file);
if(!$tmp_dir) {
// extracting failed
$app->log('Package extraction failed.', 2, false);
throw new AddonInstallerException('Package extraction failed.');
}
......@@ -141,25 +173,34 @@ class addon_installer {
if(!$addon) {
throw new AddonInstallerException('Package validation failed.');
}
$app->log('Package validated.', 0, false);
$is_update = false;
$previous = $this->getInstalledAddonVersion($addon['ident']);
if($previous !== false) {
// this is an update
if(version_compare($previous, $addon['version'], '>') && $force !== true) {
$app->log('Installed version is newer than the one to install and --force not used.', 2, false);
throw new AddonInstallerException('Installed version is newer than the one to install.');
} elseif(version_compare($previous, $addon['version'], '=') && $force !== true) {
$app->log('Installed version is the same as the one to install and --force not used.', 2, false);
throw new AddonInstallerException('Installed version is the same as the one to install.');
}
$is_update = true;
}
$app->log('Including package class file ' . $addon['class_file'], 0, false);
include $addon['class_file'];
if(!class_exists($addon['class_name'])) {
$class_name = $addon['class_name'];
if(!class_exists($class_name)) {
$app->log('Class name ' . $class_name . ' not found in class file ' . $addon['class_file'], 2, false);
throw new AddonInstallerException('Could not find main class in addon file.');
}
$class_name = $addon['class_name'];
/* @var $inst ispconfig_addon_installer_base */
$app->log('Instanciating installer class ' . $class_name, 0, false);
$inst = new $class_name();
$inst->setAddonName($addon['name']);
$inst->setAddonIdent($addon['ident']);
......@@ -178,6 +219,7 @@ class addon_installer {
exec('rm -rf ' . escapeshellarg($tmp_dir));
$app->log('Installation completed.', 0, false);
return true;
}
......
......@@ -36,6 +36,7 @@ class ispconfig_addon_installer_base {
protected function copyInterfaceFiles() {
global $conf;
$app->log('Copying interface files.', 0, false);
$install_dir = realpath($conf['rootpath'] . '/..');
if(is_dir($this->temp_dir . '/interface')) {
......@@ -44,6 +45,7 @@ class ispconfig_addon_installer_base {
$command = 'cp -rf ' . escapeshellarg($this->temp_dir . '/interface') . ' ' . escapeshellarg($install_dir . '/');
exec($command, $ret, $retval);
if($retval != 0) {
$app->log('Copying interface files failed.', 2, false);
throw new AddonInstallerException('Command ' . $command . ' failed with code ' . $retval);
}
......@@ -56,6 +58,8 @@ class ispconfig_addon_installer_base {
protected function copyServerFiles() {
global $conf;
$app->log('Copying server files.', 0, false);
$install_dir = realpath($conf['rootpath'] . '/..');
if(is_dir($this->temp_dir . '/server')) {
......@@ -64,6 +68,7 @@ class ispconfig_addon_installer_base {
$command = 'cp -rf ' . escapeshellarg($this->temp_dir . '/server'). ' ' . escapeshellarg($install_dir . '/');
exec($command, $ret, $retval);
if($retval != 0) {
$app->log('Copying interface files failed.', 2, false);
throw new AddonInstallerException('Command ' . $command . ' failed with code ' . $retval);
}
return true;
......@@ -75,9 +80,12 @@ class ispconfig_addon_installer_base {
protected function copyAddonFiles() {
global $app, $conf;
$app->log('Copying addon files.', 0, false);
$install_dir = realpath($conf['rootpath'] . '/..') . '/addons/' . $this->addon_ident;
if(!is_dir($install_dir)) {
if(!$app->system->mkdir($install_dir, false, 0750, true)) {
$app->log('Addons dir missing and could not be created.', 2, false);
throw new AddonInstallerException('Could not create addons dir ' . $install_dir);
}
}
......@@ -89,6 +97,7 @@ class ispconfig_addon_installer_base {
exec($command, $ret, $retval);
if($retval != 0) {
/* TODO: logging */
$app->log('Warning or error on copying addon files. Returncode of command ' . $command . ' was: ' . $retval .'.', 0, false);
}
return true;
......@@ -100,6 +109,7 @@ class ispconfig_addon_installer_base {
protected function executeSqlStatements() {
global $app, $conf;
$app->log('Adding addon entry to db.', 0, false);
// create addon entry if not existing
$qry = 'INSERT IGNORE INTO `addons` (`addon_ident`, `addon_version`, `addon_name`, `db_version`) VALUES (?, ?, ?, ?)';
$app->db->query($qry, $this->addon_ident, $this->addon_version, $this->addon_name, 0);
......@@ -110,6 +120,7 @@ class ispconfig_addon_installer_base {
$incremental = 0;
if($check['db_version']) {
$incremental = $check['db_version'];
$app->log('Current db version is ' . $incremental . '.', 0, false);
}
}
......@@ -121,9 +132,11 @@ class ispconfig_addon_installer_base {
if(is_file($sql_file)) {
$ret = null;
$retval = 0;
$app->log('Loading ' . $sql_file . ' into db.', 0, false);
exec($mysql_command . ' < ' . escapeshellarg($sql_file), $ret, $retval);
if($retval != 0) {
/* TODO: log error! */
$app->log('Loading ' . $sql_file . ' into db failed.', 1, false);
}
}
} else {
......@@ -135,9 +148,11 @@ class ispconfig_addon_installer_base {
} else {
$ret = null;
$retval = 0;
$app->log('Loading ' . $sql_file . ' into db.', 0, false);
exec($mysql_command . ' < ' . escapeshellarg($sql_file), $ret, $retval);
if($retval != 0) {
/* TODO: log error! */
$app->log('Loading ' . $sql_file . ' into db failed.', 1, false);
}
}
......@@ -145,6 +160,7 @@ class ispconfig_addon_installer_base {
}
$app->db->query('UPDATE `addons` SET `addon_version` = ?, `db_version` = ? WHERE `addon_ident` = ?', $this->addon_version, $new_db_version, $this->addon_ident);
$app->log('Db version of addon is now ' . $new_db_version . '.', 0, false);
}
return true;
......@@ -153,10 +169,12 @@ class ispconfig_addon_installer_base {
public function onBeforeInstall() { }
public function onInstall() {
$app->log('Running onInstall()', 0, false);
$this->copyAddonFiles();
$this->copyInterfaceFiles();
$this->copyServerFiles();
$this->executeSqlStatements();
$app->log('Finished onInstall()', 0, false);
}
public function onAfterInstall() { }
......@@ -164,10 +182,12 @@ class ispconfig_addon_installer_base {
public function onBeforeUpdate() { }
public function onUpdate() {
$app->log('Running onUpdate()', 0, false);
$this->copyAddonFiles();
$this->copyInterfaceFiles();
$this->copyServerFiles();
$this->executeSqlStatements();
$app->log('Finished onUpdate()', 0, false);
}
public function onAfterUpdate() { }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment