summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Boddie <paul@boddie.org.uk>2014-08-07 12:25:25 (GMT)
committerPaul Boddie <paul@boddie.org.uk>2014-08-07 12:25:25 (GMT)
commit10fa9029b4958df6c24a177a5daac150ad0a9e9f (patch)
tree3225d0aaf36d3f1373acf862ee1a719ee7de0db1
parent9702ca705cc7e39a19f363cb7e06a218430f4835 (diff)
downloadpykolab-10fa9029b4958df6c24a177a5daac150ad0a9e9f.tar.gz
Tidied mysql setup.
Added debconf support.
-rw-r--r--pykolab/setup/setup_mysql.py258
1 files changed, 161 insertions, 97 deletions
diff --git a/pykolab/setup/setup_mysql.py b/pykolab/setup/setup_mysql.py
index 5f8ab4a..377a3aa 100644
--- a/pykolab/setup/setup_mysql.py
+++ b/pykolab/setup/setup_mysql.py
@@ -17,9 +17,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+from glob import glob
+from os.path import exists, join
+from subprocess import call, Popen, PIPE
import os
-import subprocess
-import tempfile
import components
@@ -27,6 +28,7 @@ import pykolab
from pykolab import utils
from pykolab.constants import *
+from pykolab.setup.services import *
from pykolab.translate import _
log = pykolab.getLogger('pykolab.setup')
@@ -35,132 +37,194 @@ conf = pykolab.getConf()
def __init__():
components.register('mysql', execute, description=description())
+def cli_options():
+ mysql_group = conf.add_cli_parser_option_group(_("MySQL Options"))
+
+ mysql_group.add_option(
+ "--reset-mysql-config",
+ dest = "reset_mysql_config",
+ action = "store_true",
+ default = False,
+ help = _("Reset the MySQL configuration.")
+ )
+
def description():
return _("Setup MySQL.")
def execute(*args, **kw):
- if os.path.isfile('/bin/systemctl'):
- subprocess.call(['/bin/systemctl', 'restart', 'mysqld.service'])
- elif os.path.isfile('/sbin/service'):
- subprocess.call(['/sbin/service', 'mysqld', 'restart'])
- elif os.path.isfile('/usr/sbin/service'):
- subprocess.call(['/usr/sbin/service','mysql','restart'])
- else:
- log.error(_("Could not start the MySQL database service."))
-
- if os.path.isfile('/bin/systemctl'):
- subprocess.call(['/bin/systemctl', 'enable', 'mysqld.service'])
- elif os.path.isfile('/sbin/chkconfig'):
- subprocess.call(['/sbin/chkconfig', 'mysqld', 'on'])
- elif os.path.isfile('/usr/sbin/update-rc.d'):
- subprocess.call(['/usr/sbin/update-rc.d', 'mysql', 'defaults'])
- else:
+
+ # Signal that interaction may occur. This will involve debconf and similar
+ # system-specific mechanisms if available.
+
+ start_interaction("kolab-conf/title-mysql")
+ try:
+ _execute(*args, **kw)
+ finally:
+ stop_interaction()
+
+def _execute(*args, **kw):
+ mysql = is_debian() and 'mysql' or 'mysqld'
+
+ # Stop if MySQL is not actually installed.
+
+ if not have_mysql():
+ if conf.check_only:
+ utils.setup_status("mysql", _("not installed"))
+ else:
+ log.error(_("MySQL not installed."))
+ return
+
+ # Test MySQL daemon process availability.
+
+ if not conf.check_only and not exists('/var/run/mysqld/mysqld.sock'):
+ if not control_service(mysql, 'start'):
+ log.error(_("Could not start the MySQL database service."))
+
+ # Ensure that the service is started at boot.
+
+ if not conf.check_only and not configure_service(mysql, True):
log.error(_("Could not configure to start on boot, the " + \
"MySQL database service."))
- options = {
- 1: "Existing MySQL server (with root password already set).",
- 2: "New MySQL server (needs to be initialized)."
- }
+ # Defaults files exist in the distributions for various tasks, but such a
+ # file is used to avoid providing a password on the command line.
- answer = 0
- if os.path.exists('/var/lib/mysql/mysql.sock') or \
- os.path.exists('/var/run/mysqld/mysqld.sock') or \
- os.path.exists('/var/run/mysql/mysql.sock') or \
- os.path.exists('/var/run/mysqld/mysqld.pid'):
- answer = utils.ask_menu(_("What MySQL server are we setting up?"), options)
+ defaults_file = get_mysql_defaults()
- if answer == "1" or answer == 1:
- print >> sys.stderr, utils.multiline_message(
- _("""
- Please supply the root password for MySQL, so we can set
- up user accounts for other components that use MySQL.
- """)
- )
+ if need_mysql_root():
- mysql_root_password = utils.ask_question(
- _("MySQL root password"),
- password=True
- )
+ # If a root user can be found without any credentials being supplied, the
+ # MySQL installation probably needs a root password setting.
- else:
- print >> sys.stderr, utils.multiline_message(
- _("""
+ if have_mysql_user(None, 'root'):
+ if conf.check_only:
+ utils.setup_status("mysql", _("needs setup"))
+ return
+
+ mysql_root_password = ask_question("kolab-conf/mysql-root-new",
+ _("""
Please supply a root password for MySQL. This password
will be the administrative user for this MySQL server,
and it should be kept a secret. After this setup process
has completed, Kolab is going to discard and forget
about this password, but you will need it for
administrative tasks in MySQL.
- """)
- )
+ """),
+ _("MySQL root password"),
+ default=utils.generate_password(),
+ password=True,
+ confirm=True
+ )
+
+ p1 = Popen(['echo', "update mysql.user set Password=PASSWORD('%s') where User='root'" %
+ mysql_root_password.replace("'", "''")], stdout=PIPE)
+ p2 = Popen(['mysql'], stdin=p1.stdout)
+ p2.communicate()
+
+ call(['mysql', '-e', 'flush privileges'])
+
+ # For an installation where the root password is still needed, it is
+ # obtained here.
+
+ else:
+ mysql_root_password = ask_question("kolab-conf/mysql-root-existing",
+ _("""
+ Please supply the root password for MySQL, so we can set
+ up user accounts for other components that use MySQL.
+ """),
+ _("MySQL root password"),
+ password=True
+ )
- mysql_root_password = utils.ask_question(
- _("MySQL root password"),
- default=utils.generate_password(),
- password=True,
- confirm=True
- )
+ # Write the defaults file in order to be able to connect in future.
- p1 = subprocess.Popen(['echo', 'UPDATE mysql.user SET Password=PASSWORD(\'%s\') WHERE User=\'root\';' % (mysql_root_password)], stdout=subprocess.PIPE)
- p2 = subprocess.Popen(['mysql'], stdin=p1.stdout)
- p1.stdout.close()
- p2.communicate()
+ data = mysql_defaults % mysql_root_password
- p1 = subprocess.Popen(['echo', 'FLUSH PRIVILEGES;'], stdout=subprocess.PIPE)
- p2 = subprocess.Popen(['mysql'], stdin=p1.stdout)
- p1.stdout.close()
- p2.communicate()
+ fp = open(defaults_file, 'w')
+ os.chmod(defaults_file, 0600)
+ fp.write(data)
+ fp.close()
- data = """
-[mysql]
-user=root
-password='%s'
-""" % (mysql_root_password)
-
- fp = open('/tmp/kolab-setup-my.cnf', 'w')
- os.chmod('/tmp/kolab-setup-my.cnf', 0600)
- fp.write(data)
- fp.close()
-
- schema_file = None
- for root, directories, filenames in os.walk('/usr/share/doc/'):
- for filename in filenames:
- if filename.startswith('kolab_wap') and filename.endswith('.sql'):
- schema_file = os.path.join(root,filename)
-
- if not schema_file == None:
- p1 = subprocess.Popen(['echo', 'create database kolab;'], stdout=subprocess.PIPE)
- p2 = subprocess.Popen(['mysql', '--defaults-file=/tmp/kolab-setup-my.cnf'], stdin=p1.stdout)
- p1.stdout.close()
- p2.communicate()
-
- print >> sys.stderr, utils.multiline_message(
+ # Find the schema file for the database.
+
+ schema_file = find_schema_file()
+
+ if schema_file is not None:
+
+ # Test for the database.
+
+ if not have_mysql_database(defaults_file, 'kolab'):
+ if conf.check_only:
+ utils.setup_status("mysql", _("needs setup"))
+ return
+
+ call(['mysql', '--defaults-file=%s' % defaults_file, '-e', 'create database kolab'])
+
+ # Populate the schema.
+
+ p1 = Popen(['cat', schema_file], stdout=PIPE)
+ p2 = Popen(['mysql', '--defaults-file=%s' % defaults_file, 'kolab'], stdin=p1.stdout)
+ p2.communicate()
+
+ elif not conf.check_only:
+ log.info(_("A database called %s already exists. Not creating another one.") % 'kolab')
+
+ else:
+ log.error(_("Could not find the MySQL Kolab schema file"))
+
+ # Test for a MySQL user. Reset the user and configuration if explicitly
+ # requested or if the configuration has not been modified.
+
+ wap_url_needs_setting = conf.get('kolab_wap', 'sql_uri') == 'mysql://user:pass@localhost/database'
+
+ if have_mysql_user(defaults_file, 'kolab') and not conf.reset_mysql_config and not wap_url_needs_setting:
+
+ if not conf.check_only:
+ print >> sys.stderr, _("Kolab database account already exists and will not be configured.")
+ log.info(_("A user called %s already exists. Not creating another one.") % 'kolab')
+ else:
+ if conf.check_only:
+ utils.setup_status("mysql", _("needs setup"))
+ return
+
+ mysql_kolab_password = ask_question("kolab-conf/mysql-kolab",
_("""
Please supply a password for the MySQL user 'kolab'.
This password will be used by Kolab services, such as
the Web Administration Panel.
- """)
- )
-
- mysql_kolab_password = utils.ask_question(
+ """),
_("MySQL kolab password"),
default=utils.generate_password(),
password=True,
confirm=True
)
- p1 = subprocess.Popen(['echo', 'GRANT ALL PRIVILEGES ON kolab.* TO \'kolab\'@\'localhost\' IDENTIFIED BY \'%s\';' % (mysql_kolab_password)], stdout=subprocess.PIPE)
- p2 = subprocess.Popen(['mysql', '--defaults-file=/tmp/kolab-setup-my.cnf'], stdin=p1.stdout)
- p1.stdout.close()
- p2.communicate()
+ if not have_mysql_user(defaults_file, 'kolab'):
+ p1 = Popen(['echo', "grant all privileges on kolab.* to 'kolab'@'localhost' identified by '%s'" %
+ mysql_kolab_password.replace("'", "''")], stdout=PIPE)
+ p2 = Popen(['mysql', '--defaults-file=%s' % defaults_file], stdin=p1.stdout)
+ p2.communicate()
- p1 = subprocess.Popen(['cat', schema_file], stdout=subprocess.PIPE)
- p2 = subprocess.Popen(['mysql', '--defaults-file=/tmp/kolab-setup-my.cnf', 'kolab'], stdin=p1.stdout)
- p1.stdout.close()
- p2.communicate()
+ if wap_url_needs_setting or conf.reset_mysql_config:
+ conf.command_set('kolab_wap', 'sql_uri', 'mysql://kolab:%s@localhost/kolab' % mysql_kolab_password)
- conf.command_set('kolab_wap', 'sql_uri', 'mysql://kolab:%s@localhost/kolab' % (mysql_kolab_password))
- else:
- log.warning(_("Could not find the MySQL Kolab schema file"))
+ # If nothing needed updating, assume that the setup was done.
+
+ if conf.check_only:
+ utils.setup_status("mysql", _("setup done"))
+
+def find_schema_file():
+ for webadmin_dir in glob('/usr/share/doc/kolab*'):
+ for root, directories, filenames in os.walk(webadmin_dir):
+ for filename in filenames:
+ if filename.startswith('kolab_wap') and filename.endswith('.sql'):
+ return join(root,filename)
+ return None
+
+# Data used by the code above.
+mysql_defaults = """\
+[mysql]
+user=root
+password='%s'
+"""