Commits

Mikhail Korobov committed 6753ce2

OS autodetection

  • Participants
  • Parent commits e362580

Comments (0)

Files changed (12)

File docs/fabfile.rst

 
 .. attribute:: env.conf.OS
 
-    A string with server operating system name. Supported operating systems:
+    A string with server operating system name. Set it to the correct value if
+    autodetection fails for some reason. Supported operating systems:
 
     * lenny
     * squeeze
-
-    Default is 'lenny'.
-
-    .. warning::
-
-        Make sure this option is set properly. Deployment will fail with
-        incorrect value.
+    * maverick
 
 .. attribute:: env.conf.VCS
 

File docs/guide.rst

             env.conf = dict(
                 DB_PASSWORD = 'password',
 
-                # uncomment this for Debian Squeeze servers
-                # OS = 'squeeze',
-
                 # uncomment this line if the project is not stored in VCS
                 # default value is 'hg'
                 # VCS = 'none',
 
         my_site()
 
-   Make sure the :attr:`env.conf.OS` is correct (it is 'lenny' by default).
-
    In order to make things simple set the username in :attr:`env.hosts` string
    to your project name. It should be a valid python identifier.
    Don't worry if there is no such user on server, django-fab-deploy can

File docs/testing.rst

 Running
 -------
 
-Pass OS name (as for :attr:`env.conf.OS`) and VM name (e.g. Lenny)
-to runtests.py script::
+Pass VM name (e.g. Lenny) to runtests.py script::
 
     cd fab_deploy_tests
-    ./runtests.py <OS name> <VM name or uid>
+    ./runtests.py <VM name or uid> <what to run>
 
 Tests can take a long time to run because VM is rolled back to clean
 state before each test.
 In order to get coverage reports run::
 
     cd fab_deploy_tests
-    ./runcoverage.sh <OS name> <VM name or uid>
+    ./runcoverage.sh <VM name or uid> <what to run>
 
 html reports will be placed in ``htmlcov`` folder.

File fab_deploy/__init__.py

 from fab_deploy.deploy import *
 from fab_deploy.virtualenv import pip, pip_install, pip_update
 from fab_deploy.django_commands import migrate, manage, syncdb, compress, test, coverage
-from fab_deploy.utils import run_as, update_env, inside_project, inside_virtualenv, delete_pyc, print_env
+from fab_deploy.utils import run_as, update_env, inside_project, inside_virtualenv, delete_pyc, print_env, detect_os
 from fab_deploy.system import create_linux_account, ssh_add_key
 from fab_deploy.crontab import crontab_set, crontab_add, crontab_show, crontab_remove, crontab_update
 from fab_deploy.mysql import mysql_execute, mysql_install, mysql_create_db, mysqldump

File fab_deploy/deploy.py

 from fabric.contrib.console import confirm
 from fabric.contrib.files import upload_template
 
-from fab_deploy.utils import upload_config_template, delete_pyc, run_as
+from fab_deploy.utils import delete_pyc, run_as, detect_os
 from fab_deploy.virtualenv import pip_install, pip_update
 from fab_deploy.django_commands import compress, migrate, syncdb, test
 from fab_deploy.system import prepare_server
 
 def full_deploy():
     """ Prepares server and deploys the project. """
+    os = detect_os()
+    if not confirm("Is the OS detected correctly (%s)?" % os, default=False):
+        abort("Detection fails. Please set env.conf.OS to correct value.")
     prepare_server()
     deploy_project()
 

File fab_deploy/mysql.py

 from datetime import datetime
 from fabric.api import *
-from fab_deploy.utils import run_as, inside_project, supports_only
+from fab_deploy.utils import run_as, inside_project, detect_os
 from fab_deploy.system import aptitude_install
 
 @run_as('root')
-@supports_only('lenny, squeeze')
 def mysql_install():
     """ Installs mysql. """
     if _mysql_is_installed():
 
     # this way mysql won't ask for a password on installation
     # see http://serverfault.com/questions/19367/scripted-install-of-mysql-on-ubuntu
+    os = detect_os()
     aptitude_install('debconf-utils')
     passwd=env.conf['DB_PASSWORD']
 
-    mysql_versions = {'lenny': '5.0', 'squeeze': '5.1'}
-    version = mysql_versions[env.conf.OS]
+    mysql_versions = {'lenny': '5.0', 'squeeze': '5.1', 'maverick': '5.1'}
+    version = mysql_versions[os]
 
     debconf_defaults = [
-        "mysql-server-%s\tmysql-server/root_password_again\tpassword\t%s" % (version, passwd),
-        "mysql-server-%s\tmysql-server/root_password\tpassword\t%s" % (version, passwd),
+        "mysql-server-%s mysql-server/root_password_again password %s" % (version, passwd),
+        "mysql-server-%s mysql-server/root_password password %s" % (version, passwd),
     ]
+
     run("echo '%s' | debconf-set-selections" % "\n".join(debconf_defaults))
 
     warn('\n=========\nThe password for mysql "root" user will be set to "%s"\n=========\n' % passwd)
     """ Executes passed sql command using mysql shell. """
     user = user or env.conf['DB_USER']
     password = env.conf['DB_PASSWORD'] if password is None else password
-    run ("echo '%s' | mysql -u%s -p%s" % (sql, user , password))
+    return run("echo '%s' | mysql -u%s -p%s" % (sql, user , password))
 
 def mysql_create_db():
     """ Creates an empty mysql database. """

File fab_deploy/nginx.py

 from fabric.api import run, env, settings
-from fab_deploy.utils import run_as, upload_config_template, supports_only
+from fab_deploy.utils import run_as, upload_config_template, detect_os
 from fab_deploy.system import aptitude_install
 from fab_deploy.apache import _apache_setup_port
 
 @run_as('root')
-@supports_only('lenny, squeeze')
 def nginx_install():
     """ Installs nginx. """
-    options = {
-        'lenny': '-t lenny-backports',
-        'squeeze': '',
-    }
-    aptitude_install('nginx', options[env.conf.OS])
+    os = detect_os()
+    options = {'lenny': '-t lenny-backports'}
+    aptitude_install('nginx', options.get(os, ''))
     run('rm -f /etc/nginx/sites-enabled/default')
 
 @run_as('root')

File fab_deploy/system.py

 import os.path
 from fabric.api import run, settings, env, cd
 from fabric.contrib.files import append
-from fab_deploy.utils import run_as, supports_only
+from fab_deploy.utils import run_as, detect_os
+from fabric.utils import puts
 
 def prepare_server():
     """ Prepares server: installs system packages. """
     install_common_software()
 
 @run_as('root')
-@supports_only('lenny, squeeze')
 def install_common_software():
     """ Installs common system packages. """
+    os = detect_os()
     common_packages = [
         'python', 'build-essential', 'python-dev', 'python-setuptools',
         'python-profiler', 'libjpeg-dev', 'zlib1g-dev',
         'lenny': ['libmysqlclient15-dev'],
         'squeeze': ['libmysqlclient-dev'],
     }
-
-    aptitude_install(" ".join(common_packages + extra_packages[env.conf.OS]))
+    if os in extra_packages:
+        aptitude_install(" ".join(common_packages + extra_packages[os]))
 
     # git and mercurial are outdated in stable Debian Lenny and
     # don't work with some source repositories on github and bitbucket
-    vcs_options = {
-        'lenny': '-t lenny-backports',
-        'squeeze': '',
-    }
-    aptitude_install('mercurial git', vcs_options[env.conf.OS])
+    vcs_options = {'lenny': '-t lenny-backports'}
+    aptitude_install('mercurial git', vcs_options.get(os, ""))
     aptitude_install('bzr', '--without-recommends')
 
     run('easy_install -U pip')
 
 
 @run_as('root')
-@supports_only('lenny, squeeze')
 def setup_backports():
     """ Adds backports repo to apt sources. """
+    os = detect_os()
     backports = {
         'lenny': 'http://backports.debian.org/debian-backports lenny-backports main contrib non-free',
         'squeeze': 'http://backports.debian.org/debian-backports squeeze-backports main contrib non-free',
     }
-    run("echo 'deb %s' > /etc/apt/sources.list.d/backports.sources.list" % backports[env.conf.OS])
+
+    if os not in backports:
+        puts("Backports are not available for " + os)
+        return
+
+    run("echo 'deb %s' > /etc/apt/sources.list.d/backports.sources.list" % backports[os])
     with settings(warn_only=True):
         run('aptitude update')
 

File fab_deploy/tests/__init__.py

+

File fab_deploy/utils.py

 import os
 import pprint
+from re import match
 from functools import wraps
 from fabric.contrib.files import upload_template
 from fabric.api import *
 from fabric.state import _AttributeDict
 from fabric.network import normalize, join_host_strings
 
-SUPPORTED_SYSTEMS = ['lenny', 'squeeze']
+def _codename(distname, version, id):
+    patterns = [
+        ('lenny', ('debian', '^5', '')),
+        ('squeeze', ('debian', '^6', '')),
+        ('maverick', ('Ubuntu', '^10.10', '')),
+    ]
+    for name, p in patterns:
+        if match(p[0], distname) and match(p[1], version) and match(p[2], id):
+            return name
+
+def detect_os():
+    if 'conf' in env and 'OS' in env.conf:
+        return env.conf['OS']
+    output = run('python -c "import platform; print platform.dist()"')
+    name = _codename(*eval(output))
+    puts('%s detected' % name)
+    return name
 
 def run_as(user):
     """
         return inner
     return decorator
 
-def supports_only(supported_systems):
-    """ Safety decorator. Marks command as only supported for a set of
-    operating systems. Aborts execution if :attr:`env.conf.OS` is not in
-    list. Accepts string with comma-separated list of system names::
-
-        @supports_only('lenny, squeeze')
-        def my_command():
-            pass
-
-    """
-    systems = [s.strip().lower() for s in supported_systems.split(',')]
-    def decorator(func):
-        @wraps(func)
-        def inner(*args, **kwargs):
-            if env.conf.OS not in systems:
-                abort('%s is not supported. Supported operating systems: %s' % (
-                    env.conf.OS, supported_systems))
-            return func(*args, **kwargs)
-        return inner
-    return decorator
-
-
 def upload_config_template(name, to=None):
     if to is None:
         base_dir = env.conf['ENV_DIR'] + "/etc/"
         THREADS = 15,
         SERVER_NAME = host,
         SERVER_ADMIN = 'example@example.com',
-        OS = 'lenny',
         VCS = 'hg',
 
         # these options shouldn't be set by user
         if env.conf.VCS == vcs:
             env.conf.VCS = 'fab_deploy.vcs.'+vcs
 
-    if env.conf.OS not in SUPPORTED_SYSTEMS:
-        abort('%s is not supported. Supported operating systems: %s' % (
-            env.conf.OS, ', '.join(SUPPORTED_SYSTEMS)
-        ))
 
 def virtualenv():
     """

File fab_deploy/virtualenv.py

-from fabric.api import run, env, cd, env, prefix
+from fabric.api import run, env, cd
 from fab_deploy.apache import touch
-from fab_deploy.utils import run_as, inside_project
+from fab_deploy.utils import inside_project
 
 @inside_project
 def pip(commands=''):

File fab_deploy_tests/preparevm.py

     box.snapshot('restore', name)
     box.start()
 
-def deep_prepare(os, name):
+def deep_prepare(name):
     """ Deep VM preparation for test speedups.
     Should only be run if all related tests are passed.
     It prepares 3 snapshots:
     env.hosts = ['foo@127.0.0.1:2222']
     env.password = '123'
     env.disable_known_hosts = True
-    env.conf = {'DB_PASSWORD': '123', 'OS': os}
+    env.conf = {'DB_PASSWORD': '123'}
     update_env()
 
     box = VirtualBox(name)
 
 
 if __name__ == '__main__':
-    deep_prepare(sys.argv[1], sys.argv[2])
+    deep_prepare(sys.argv[1])