muhuk's blog

Nature, to Be Commanded, Must Be Obeyed

May 22, 2010

How to Install MySQL with Fabric

I just want to share a small fabfile snipplet that installs mysql-server package on a Debian machine if it’s not already installed. Actually it should have been quite straightforward; just issue an apt-get command, right? But during configuration it displays a curses dialog for MySQL root password. This of course blows your automated configuration plans. We will seed this value to debconf database to avoid this dialog.

First let’s have a look at the supporting code:

from __future__ import with_statement
from fabric.api import *
from fabric.utils import warn


def apt_get(*packages):
    sudo('apt-get -y --no-upgrade install %s' % ' '.join(packages), shell=False)

Our apt_get fabric command issues apt_get install that answers yes to all questions and does not upgrade if the requested package is already installed. Now let’s take a look at the main command that installs mysql-server

def install_mysql():
    with settings(hide('warnings', 'stderr'), warn_only=True):
        result = sudo('dpkg-query --show mysql-server')
    if result.failed is False:
        warn('MySQL is already installed')
        return
    mysql_password = prompt('Please enter MySQL root password:')
    sudo('echo "mysql-server-5.0 mysql-server/root_password password ' \
                              '%s" | debconf-set-selections' % mysql_password)
    sudo('echo "mysql-server-5.0 mysql-server/root_password_again password ' \
                              '%s" | debconf-set-selections' % mysql_password)
    apt_get('mysql-server')

First we want to make sure mysql-server is not already installed. For this reason we issue dpkg-query --show mysql-server. Note that if this command fails then mysql-server is not installed and we can proceed otherwise we want to return. We hide the ugly error messages by running our dpkg-query command within a settings context:

with settings(hide('warnings', 'stderr'), warn_only=True):
    result = sudo('dpkg-query --show mysql-server')
if result.failed is False:
    warn('MySQL is already installed')
    return

The rest of the code is pretty straightforward. We prompt to the user running fabric for the root password and seed its value twice into the debconf database:

sudo('echo "mysql-server-5.0 mysql-server/root_password password ' \
                            '%s" | debconf-set-selections' % mysql_password)
sudo('echo "mysql-server-5.0 mysql-server/root_password_again password ' \
                            '%s" | debconf-set-selections' % mysql_password)
apt_get('mysql-server')

Finally, having finished our little dance, we install mysql-server. I hope this helps some automated deployment believer out there.

If you have any questions, suggestions or corrections feel free to drop me a line.