Source

caktus-deployment / mallet / client_vm.py

Full commit
import os

import mallet
import logging
from mallet.bootstrap import apt
from mallet.bootstrap.apt import lenny
from mallet.utils import create_ssh, call, write, writelines, chown
from mallet.bootstrap.base import PackageGroup

from libcloud.types import Provider
from fabric.api import settings, env


logger = logging.getLogger('mallet.client_vm')


class SCM(PackageGroup):
    packages = ['subversion', 'git-core', 'mercurial']


class BuildEssential(PackageGroup):
    packages = ['build-essential']


class SSH(PackageGroup):
    packages = ['openssh-server']

    def post_install(self, node_wrapper):
        config = env.cfg.config
        if config.has_option('mallet', 'public_key'):
            call(['mkdir', '-p', '/root/.ssh'])
            public_key = open(config.get('mallet', 'public_key')).read()
            write('/root/.ssh/authorized_keys', public_key, append=True)


class Postgres(lenny.Postgres):
    packages = ['postgresql', 'postgresql-server-dev-8.4', 'pwgen']

    def post_install(self, node_wrapper):
        call(['locale-gen', 'en_US.UTF-8'])
        call(['update-locale', 'LANG=en_US.UTF-8'])
        call(['pg_dropcluster', '--stop', '8.4', 'main'])
        call(['pg_createcluster', '--start', '-e', 'UTF-8', '8.4', 'main'])


class Python(PackageGroup):
    packages = ['ipython', 'python-setuptools', 'python-dev', 'libpq-dev',
                'libapache2-mod-wsgi', 'python-imaging']

    def post_install(self, node_wrapper):
        call(['easy_install', '-U', 'pip'])
        call(['pip', 'install', '-U', 'virtualenv'])
        call(['pip', 'install', '-U', 'distribute'])
        call(['pip', 'install', '-U', 'distribute'])
        call(['pip', 'install', '-U', 'psycopg2'])


class Apache(lenny.Apache):

    def post_install(self, node_wrapper):
        super(Apache, self).post_install(node_wrapper)
        logger.info('Creating clients group')
        call(['addgroup', 'clients'])
        logger.info('Creating sudoers file')
        sudoers = ['%clients ALL=NOPASSWD: /etc/init.d/apache2 '
                   'reload, /etc/init.d/apache2 restart']
        writelines('/etc/sudoers', sudoers)


class NodeWrapper(mallet.NodeWrapper):

    def hostname(self):
        ssh_conn = create_ssh(self.node.public_ip[0], username='root')
        with settings(ssh_conn=ssh_conn):
            call(['hostname'])

    def add_client(self, name):
        ssh_conn = create_ssh(self.node.public_ip[0], username='root')
        with settings(ssh_conn=ssh_conn):
            call(['groupadd', 'clients'])
            logger.info('Creating user account')
            call(['useradd', '-G', 'clients', '-m',
                  '-s', '/bin/bash', name])
            # TODO add configuration option for database type
            logger.info('Creating database user')
            call(['sudo', '-u', 'postgres', 'createuser', '--no-superuser',
                  '--createdb', '--no-createrole', name])
            call(['sudo', '-u', 'postgres', 'createdb', name, '-O', name])

            # TODO add configuration option for apache
            logger.info('Adding Apache configuration')
            call(['sudo', '-u', name, 'mkdir',
                 '/home/%s/apache.conf.d/' % name])
            apache_conf = """
# Include user-controlled apache configs
Include /home/%(name)s/apache.conf.d/*
""" % {'name': name}
            write('/etc/apache2/sites-available/%s' % name, apache_conf)
            call(['a2ensite', name])
            call(['/etc/init.d/apache2', 'reload'])
            
            # add SSH public key
            config = env.cfg.config
            if config.has_option('mallet', 'public_key'):
                ssh_dir = os.path.join('/', 'home', name, '.ssh')
                call(['sudo', '-u', name, 'mkdir -p %s' % ssh_dir])
                public_key = open(config.get('mallet', 'public_key')).read()
                authorized_keys = os.path.join(ssh_dir, 'authorized_keys')
                write(authorized_keys, public_key, append=True)
                chown(authorized_keys, name)

            # logger.info('Setting password for user')
            # print 'Please choose a UNIX password for the "%s" user' % name
            # call(['passwd', name])


class SampleTemplate(mallet.Template):

    provider = Provider.RACKSPACE
    driver_config = {'image_id': 14362, 'size_id': 1}
    distribution = apt.Apt
    release = lenny.Lenny
    packages = [
        Apache,
        Postgres,
        Python,
        lenny.Memcache,
        BuildEssential,
        SSH,
        SCM,
    ]
    node_wrapper = NodeWrapper