From 3250e5e37c27acf09d03c89270b5b8e98b7072fa Mon Sep 17 00:00:00 2001 From: tbrehm Date: Tue, 13 Jul 2010 11:43:53 +0000 Subject: [PATCH] Implemented: FS#1219 - Add support for incremental updates of the ispconfig database structure --- install/lib/install.lib.php | 37 +++++++++++ install/lib/installer_base.lib.php | 7 +- install/lib/update.lib.php | 97 ++++++++++++++++++++++------ install/sql/README.txt | 39 +++++++++++ install/sql/incremental/upd_0000.sql | 5 ++ install/sql/ispconfig3.sql | 1 + 6 files changed, 163 insertions(+), 23 deletions(-) create mode 100644 install/sql/README.txt create mode 100644 install/sql/incremental/upd_0000.sql diff --git a/install/lib/install.lib.php b/install/lib/install.lib.php index 3c2adc129..a4e388054 100644 --- a/install/lib/install.lib.php +++ b/install/lib/install.lib.php @@ -640,6 +640,43 @@ function is_installed($appname) { } } +/* + * Compare ISPConfig version number. + * return values: + * -1 $current version is newer then $new version (downgrade) + * 0 $current version = $new version + * 1 $current version is older then new version (update) + +*/ +function compare_ispconfig_version($current,$new) { + if( $current == $new) { + return 0; + } + + $p = explode('.',$current); + $tmp = ''; + $tmp .= str_pad(intval($p[0]), 3, '0', STR_PAD_LEFT); + $tmp .= (isset($p[1]))?str_pad(intval($p[1]), 3, '0', STR_PAD_LEFT):'000'; + $tmp .= (isset($p[2]))?str_pad(intval($p[2]), 3, '0', STR_PAD_LEFT):'000'; + $tmp .= (isset($p[3]))?str_pad(intval($p[3]), 3, '0', STR_PAD_LEFT):'000'; + $current = $tmp; + + $p = explode('.',$new); + $tmp = ''; + $tmp .= str_pad(intval($p[0]), 3, '0', STR_PAD_LEFT); + $tmp .= (isset($p[1]))?str_pad(intval($p[1]), 3, '0', STR_PAD_LEFT):'000'; + $tmp .= (isset($p[2]))?str_pad(intval($p[2]), 3, '0', STR_PAD_LEFT):'000'; + $tmp .= (isset($p[3]))?str_pad(intval($p[3]), 3, '0', STR_PAD_LEFT):'000'; + $new = $tmp; + + if($new > $current) { + return 1; + } else { + return -1; + } + +} + ?> diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php index cb489b519..e6409ae2c 100644 --- a/install/lib/installer_base.lib.php +++ b/install/lib/installer_base.lib.php @@ -196,7 +196,8 @@ class installer_base { $tpl_ini_array = ini_to_array(rf('tpl/server.ini.master')); - // TODO: Update further distribution specific parameters for server config here + //* Update further distribution specific parameters for server config here + //* HINT: Every line added here has to be added in update.lib.php too!! $tpl_ini_array['web']['vhost_conf_dir'] = $conf['apache']['vhost_conf_dir']; $tpl_ini_array['web']['vhost_conf_enabled_dir'] = $conf['apache']['vhost_conf_enabled_dir']; $tpl_ini_array['jailkit']['jailkit_chroot_app_programs'] = $conf['jailkit']['jailkit_chroot_app_programs']; @@ -637,8 +638,6 @@ class installer_base { //* configure pam for SMTP authentication agains the ispconfig database $configfile = 'pamd_smtp'; if(is_file("$pam/smtp")) copy("$pam/smtp", "$pam/smtp~"); - // On some OSes smtp is world readable which allows for reading database information. Removing world readable rights should have no effect. - if(is_file("$pam/smtp")) exec("chmod o= $pam/smtp"); if(is_file("$pam/smtp~")) exec("chmod 400 $pam/smtp~"); $content = rf("tpl/$configfile.master"); @@ -647,6 +646,8 @@ class installer_base { $content = str_replace('{mysql_server_database}', $conf['mysql']['database'], $content); $content = str_replace('{mysql_server_ip}', $conf['mysql']['ip'], $content); wf("$pam/smtp", $content); + // On some OSes smtp is world readable which allows for reading database information. Removing world readable rights should have no effect. + if(is_file("$pam/smtp")) exec("chmod o= $pam/smtp"); exec("chmod 660 $pam/smtp"); exec("chown daemon:daemon $pam/smtp"); diff --git a/install/lib/update.lib.php b/install/lib/update.lib.php index 81f896002..874f3fd0f 100644 --- a/install/lib/update.lib.php +++ b/install/lib/update.lib.php @@ -68,6 +68,7 @@ function updateDbAndIni() { //* Update $conf array with values from the server.ini that shall be preserved $tmp = $inst->db->queryOneRecord("SELECT * FROM ".$conf["mysql"]["database"].".server WHERE server_id = ".$conf['server_id']); $ini_array = ini_to_array(stripslashes($tmp['config'])); + $current_db_version = (isset($tmp['dbversion']))?intval($tmp['dbversion']):0; if(count($ini_array) == 0) die('Unable to read server configuration from database.'); @@ -78,31 +79,61 @@ function updateDbAndIni() { $conf['services']['db'] = ($tmp['db_server'] == 1)?true:false; $conf['services']['vserver'] = ($tmp['vserver_server'] == 1)?true:false; $conf['postfix']['vmail_mailbox_base'] = $ini_array['mail']['homedir_path']; - - //** Delete the old database - if( !$inst->db->query('DROP DATABASE IF EXISTS '.$conf['mysql']['database']) ) { - + + //* Do incremental DB updates only on installed ISPConfig versions > 3.0.3 + if(compare_ispconfig_version('3.0.3',ISPC_APP_VERSION) >= 0) { + + swriteln($inst->lng('Starting incremental database update.')); + + //* get the version of the db schema from the server table + $found = true; + while($found == true) { + $next_db_version = intval($current_db_version + 1); + $patch_filename = realpath(dirname(__FILE__).'/../').'/sql/incremental/upd_'.str_pad($next_db_version, 4, '0', STR_PAD_LEFT).'.sql'; + if(is_file($patch_filename)) { + //* Load patch file into database + if( !empty($conf["mysql"]["admin_password"]) ) { + system("mysql --default-character-set=".$conf['mysql']['charset']." --force -h '".$conf['mysql']['host']."' -u '".$conf['mysql']['admin_user']."' -p'".$conf['mysql']['admin_password']."' ".$conf['mysql']['database']." < ".$patch_filename); + } else { + system("mysql --default-character-set=".$conf['mysql']['charset']." --force -h '".$conf['mysql']['host']."' -u '".$conf['mysql']['admin_user']."' ".$conf['mysql']['database']." < ".$patch_filename); + } + swriteln($inst->lng('Loading SQL patch file').': '.$patch_filename); + $current_db_version = $next_db_version; + } else { + $found = false; + } + } + + //* update the database version in server table + $inst->db->query("UPDATE ".$conf["mysql"]["database"].".server SET dbversion = '".$current_db_version."' WHERE server_id = ".$conf['server_id']); + + + //* If ISPConfig Version < 3.0.3, we will do a full db update + } else { + + swriteln($inst->lng('Starting full database update.')); + + //** Delete the old database + if( !$inst->db->query('DROP DATABASE IF EXISTS '.$conf['mysql']['database']) ) { $inst->error('Unable to drop MySQL database: '.$conf['mysql']['database'].'.'); - } - - //** Create the mysql database - $inst->configure_database(); - - //** empty all databases - $db_tables = $inst->db->getTables(); - - foreach($db_tables as $table) { + } - $inst->db->query("TRUNCATE $table"); - } + //** Create the mysql database + $inst->configure_database(); - //** load old data back into database - if( !empty($conf["mysql"]["admin_password"]) ) { + //** empty all databases + $db_tables = $inst->db->getTables(); - system("mysql --default-character-set=".$conf['mysql']['charset']." --force -h '".$conf['mysql']['host']."' -u '".$conf['mysql']['admin_user']."' -p'".$conf['mysql']['admin_password']."' ".$conf['mysql']['database']." < existing_db.sql"); - } else { + foreach($db_tables as $table) { + $inst->db->query("TRUNCATE $table"); + } - system("mysql --default-character-set=".$conf['mysql']['charset']." --force -h '".$conf['mysql']['host']."' -u '".$conf['mysql']['admin_user']."' ".$conf['mysql']['database']." < existing_db.sql"); + //** load old data back into database + if( !empty($conf["mysql"]["admin_password"]) ) { + system("mysql --default-character-set=".$conf['mysql']['charset']." --force -h '".$conf['mysql']['host']."' -u '".$conf['mysql']['admin_user']."' -p'".$conf['mysql']['admin_password']."' ".$conf['mysql']['database']." < existing_db.sql"); + } else { + system("mysql --default-character-set=".$conf['mysql']['charset']." --force -h '".$conf['mysql']['host']."' -u '".$conf['mysql']['admin_user']."' ".$conf['mysql']['database']." < existing_db.sql"); + } } @@ -111,6 +142,32 @@ function updateDbAndIni() { $old_ini_array = ini_to_array(stripslashes($tmp_server_rec['config'])); unset($tmp_server_rec); $tpl_ini_array = ini_to_array(rf('tpl/server.ini.master')); + + //* Update further distribution specific parameters for server config here + //* HINT: Every line added here has to be added in installer_base.lib.php too!! + $tpl_ini_array['web']['vhost_conf_dir'] = $conf['apache']['vhost_conf_dir']; + $tpl_ini_array['web']['vhost_conf_enabled_dir'] = $conf['apache']['vhost_conf_enabled_dir']; + $tpl_ini_array['jailkit']['jailkit_chroot_app_programs'] = $conf['jailkit']['jailkit_chroot_app_programs']; + $tpl_ini_array['fastcgi']['fastcgi_phpini_path'] = $conf['fastcgi']['fastcgi_phpini_path']; + $tpl_ini_array['fastcgi']['fastcgi_starter_path'] = $conf['fastcgi']['fastcgi_starter_path']; + $tpl_ini_array['server']['hostname'] = $conf['hostname']; + $tpl_ini_array['server']['ip_address'] = @gethostbyname($conf['hostname']); + $tpl_ini_array['web']['website_basedir'] = $conf['web']['website_basedir']; + $tpl_ini_array['web']['website_path'] = $conf['web']['website_path']; + $tpl_ini_array['web']['website_symlinks'] = $conf['web']['website_symlinks']; + $tpl_ini_array['cron']['crontab_dir'] = $conf['cron']['crontab_dir']; + $tpl_ini_array['web']['security_level'] = 20; + $tpl_ini_array['web']['user'] = $conf['apache']['user']; + $tpl_ini_array['web']['group'] = $conf['apache']['group']; + $tpl_ini_array['web']['php_ini_path_apache'] = $conf['apache']['php_ini_path_apache']; + $tpl_ini_array['web']['php_ini_path_cgi'] = $conf['apache']['php_ini_path_cgi']; + $tpl_ini_array['mail']['pop3_imap_daemon'] = ($conf['dovecot']['installed'] == true)?'dovecot':'courier'; + $tpl_ini_array['mail']['mail_filter_syntax'] = ($conf['dovecot']['installed'] == true)?'sieve':'maildrop'; + $tpl_ini_array['dns']['bind_user'] = $conf['bind']['bind_user']; + $tpl_ini_array['dns']['bind_group'] = $conf['bind']['bind_group']; + $tpl_ini_array['dns']['bind_zonefiles_dir'] = $conf['bind']['bind_zonefiles_dir']; + $tpl_ini_array['dns']['named_conf_path'] = $conf['bind']['named_conf_path']; + $tpl_ini_array['dns']['named_conf_local_path'] = $conf['bind']['named_conf_local_path']; // update the new template with the old values if(is_array($old_ini_array)) { diff --git a/install/sql/README.txt b/install/sql/README.txt new file mode 100644 index 000000000..7159cfc37 --- /dev/null +++ b/install/sql/README.txt @@ -0,0 +1,39 @@ + +--------------------------------------------------------------------------------- +- Developer README +--------------------------------------------------------------------------------- + +When you add or modify a database field or table in the ISPConfig database, +then follow these steps: + +1) Add the field or table in the ispconfig3.sql file. This file contains the + complete database dump which is used when ISPConfig gets installed. + +2) Create a new file in the "incremental" subfolder wich contains the alter + table, or if it is a complete new table then the add table, statement(s) in + MySQL syntax which is/are required to modify the current ispconfig database + during update. The naming scheme of the sql patch update files is + upd_0001.sql, upd_0002.sql, upd_0003.sql etc. Ensure that the number that + you choose for the new file is a +1 increment of the number of the last + existing file and that the number is formatted with 4 digits. + + A patch file may contain one or more alter table statements. Every patch file + gets executed once in the database, so do not modify older (already released) + patch files, they will not get executed again if the update was already run + once on a system. + + After a patch has been executed, the dbversion field in the server table gets + increeased to the version number of the last installed patch. + + If you like to run a patch file again for testing purposes on your dev machine, + then set the number in "dbversion" field of the server table to be lower then + the number of your patch. + +Note: Incremental patches are supported for installed ISPConfig versions > 3.0.3. + If the installed version is < 3.0.3, then the full update method is used. + In other words, ISPConfig 3.0.3 is the patch release (dbversion) 0 as the + incremental update feature has been introduced in 3.0.3. + + + + diff --git a/install/sql/incremental/upd_0000.sql b/install/sql/incremental/upd_0000.sql new file mode 100644 index 000000000..891cfa390 --- /dev/null +++ b/install/sql/incremental/upd_0000.sql @@ -0,0 +1,5 @@ +-- ----------------------------------------------------------- +-- Dummy patch file +-- Do not edit this file +-- See README.txt in sql folder for detailed instructions +-- ----------------------------------------------------------- \ No newline at end of file diff --git a/install/sql/ispconfig3.sql b/install/sql/ispconfig3.sql index 504886bed..694ba9ba0 100644 --- a/install/sql/ispconfig3.sql +++ b/install/sql/ispconfig3.sql @@ -659,6 +659,7 @@ CREATE TABLE `server` ( `config` text NOT NULL, `updated` bigint(20) unsigned NOT NULL default '0', `mirror_server_id` int(11) unsigned NOT NULL default '0', + `dbversion` int(11) unsigned NOT NULL default '0', `active` tinyint(1) NOT NULL default '1', PRIMARY KEY (`server_id`) ) ENGINE=MyISAM AUTO_INCREMENT=1; -- GitLab