diff options
author | Neil Williams <codehelp@debian.org> | 2015-08-15 14:33:59 +0200 |
---|---|---|
committer | Neil Williams <codehelp@debian.org> | 2015-08-16 14:28:35 +0200 |
commit | 54b1ab7ea71a857791189d7a2108c8b76cbfde2a (patch) | |
tree | 1515a90e7e8a8986277adc2654f001e8ecdbcce0 /vmdebootstrap/base.py | |
parent | ca8829488c49ae4801ef91eed6d17f7bad892eef (diff) | |
download | vmdebootstrap-54b1ab7ea71a857791189d7a2108c8b76cbfde2a.tar.gz |
move handlers into a module directory
Diffstat (limited to 'vmdebootstrap/base.py')
-rw-r--r-- | vmdebootstrap/base.py | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/vmdebootstrap/base.py b/vmdebootstrap/base.py new file mode 100644 index 0000000..c2799e7 --- /dev/null +++ b/vmdebootstrap/base.py @@ -0,0 +1,133 @@ +""" + Base for common utility functions +""" +# -*- coding: utf-8 -*- +# +# base.py +# +# Copyright 2015 Neil Williams <codehelp@debian.org> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os +import crypt +import cliapp +import logging +import subprocess + +# pylint: disable=missing-docstring + + +def runcmd(argv, stdin='', ignore_fail=False, env=None, **kwargs): + logging.debug('runcmd: %s %s %s', argv, env, kwargs) + proc = subprocess.Popen( + argv, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + env=env, **kwargs) + out, err = proc.communicate(stdin) + if proc.returncode != 0: + msg = 'command failed: %s\n%s\n%s' % (argv, out, err) + logging.error(msg) + if not ignore_fail: + raise cliapp.AppException(msg) + return out + + +def mount_wrapper(rootdir): + runcmd(['mount', '/dev', '-t', 'devfs', '-obind', + '%s' % os.path.join(rootdir, 'dev')]) + runcmd(['mount', '/proc', '-t', 'proc', '-obind', + '%s' % os.path.join(rootdir, 'proc')]) + runcmd(['mount', '/sys', '-t', 'sysfs', '-obind', + '%s' % os.path.join(rootdir, 'sys')]) + + +def umount_wrapper(rootdir): + runcmd(['umount', os.path.join(rootdir, 'sys')]) + runcmd(['umount', os.path.join(rootdir, 'proc')]) + runcmd(['umount', os.path.join(rootdir, 'dev')]) + + +def cleanup_apt_cache(rootdir): + out = runcmd(['chroot', rootdir, 'apt-get', 'clean']) + logging.debug('stdout:\n%s', out) + + +def set_password(rootdir, user, password): + encrypted = crypt.crypt(password, '..') + runcmd(['chroot', rootdir, 'usermod', '-p', encrypted, user]) + + +def delete_password(rootdir, user): + runcmd(['chroot', rootdir, 'passwd', '-d', user]) + + +class Base(object): + + name = 'base' + + def __init__(self): + super(Base, self).__init__() + self.settings = None + + def define_settings(self, settings): + self.settings = settings + + def message(self, msg): + logging.info(msg) + if self.settings['verbose']: + print msg + + def create_empty_image(self): + self.message('Creating disk image') + runcmd(['qemu-img', 'create', '-f', 'raw', + self.settings['image'], + str(self.settings['size'])]) + + def create_tarball(self, rootdir): + # Create a tarball of the disk's contents + # shell out to runcmd since it more easily handles rootdir + self.message('Creating tarball of disk contents') + runcmd(['tar', '-cf', self.settings['tarball'], '-C', rootdir, '.']) + + def mkfs(self, device, fstype): + self.message('Creating filesystem %s' % fstype) + runcmd(['mkfs', '-t', fstype, device]) + + def set_root_password(self, rootdir): + if self.settings['root-password']: + self.message('Setting root password') + set_password(rootdir, 'root', self.settings['root-password']) + elif self.settings['lock-root-password']: + self.message('Locking root password') + runcmd(['chroot', rootdir, 'passwd', '-l', 'root']) + else: + self.message('Give root an empty password') + delete_password(rootdir, 'root') + + def create_users(self, rootdir): + def create_user(vmuser): + runcmd(['chroot', rootdir, 'adduser', '--gecos', vmuser, + '--disabled-password', vmuser]) + if self.settings['sudo']: + runcmd(['chroot', rootdir, 'adduser', vmuser, 'sudo']) + + for userpass in self.settings['user']: + if '/' in userpass: + user, password = userpass.split('/', 1) + create_user(user) + set_password(rootdir, user, password) + else: + create_user(userpass) + delete_password(rootdir, userpass) |