diff options
author | Neil Williams <codehelp@debian.org> | 2015-08-15 17:01:37 +0200 |
---|---|---|
committer | Neil Williams <codehelp@debian.org> | 2015-08-16 14:28:53 +0200 |
commit | 4076819572f4dec90050771a58a4753d20a3f68b (patch) | |
tree | 633060d5b03ef7f323368c0dc345c9334b04f9fd /vmdebootstrap/filesystem.py | |
parent | 54b1ab7ea71a857791189d7a2108c8b76cbfde2a (diff) | |
download | vmdebootstrap-4076819572f4dec90050771a58a4753d20a3f68b.tar.gz |
add setuptools support
Diffstat (limited to 'vmdebootstrap/filesystem.py')
-rw-r--r-- | vmdebootstrap/filesystem.py | 233 |
1 files changed, 232 insertions, 1 deletions
diff --git a/vmdebootstrap/filesystem.py b/vmdebootstrap/filesystem.py index e0a16d9..1ccaeed 100644 --- a/vmdebootstrap/filesystem.py +++ b/vmdebootstrap/filesystem.py @@ -20,7 +20,14 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -from vmdebootstrap.base import Base + +import os +import cliapp +import logging +import subprocess +from vmdebootstrap.base import Base, runcmd + +# pylint: disable=missing-docstring class Filesystem(Base): @@ -29,3 +36,227 @@ class Filesystem(Base): def __init__(self): super(Filesystem, self).__init__() + self.settings = None + self.devices = { + 'rootdir': None, + 'rootdev': None, + 'bootdev': None, + 'boottype': None, + 'roottype': None, + 'swapdev': None, + } + + def define_settings(self, settings): + self.settings = settings + self.devices['roottype'] = self.settings['roottype'] + + def chown(self): + if not self.settings['owner']: + return + # Change image owner after completed build + if self.settings['image']: + filename = self.settings['image'] + elif self.settings['tarball']: + filename = self.settings['tarball'] + else: + return + self.message("Changing owner to %s" % self.settings["owner"]) + subprocess.call(["chown", self.settings["owner"], filename]) + + def update_initramfs(self): + rootdir = self.devices['rootdir'] + if not rootdir: + raise cliapp.AppException("rootdir not set") + cmd = os.path.join('usr', 'sbin', 'update-initramfs') + if os.path.exists(os.path.join(str(rootdir), cmd)): + self.message("Updating the initramfs") + runcmd(['chroot', rootdir, cmd, '-u']) + + def setup_kpartx(self): + bootindex = None + swapindex = None + out = runcmd(['kpartx', '-avs', self.settings['image']]) + if self.settings['bootsize'] and self.settings['swap'] > 0: + bootindex = 0 + rootindex = 1 + swapindex = 2 + parts = 3 + elif self.settings['use-uefi']: + bootindex = 0 + rootindex = 1 + parts = 2 + elif self.settings['use-uefi'] and self.settings['swap'] > 0: + bootindex = 0 + rootindex = 1 + swapindex = 2 + parts = 3 + elif self.settings['bootsize']: + bootindex = 0 + rootindex = 1 + parts = 2 + elif self.settings['swap'] > 0: + rootindex = 0 + swapindex = 1 + parts = 2 + else: + rootindex = 0 + parts = 1 + boot = None + swap = None + devices = [line.split()[2] + for line in out.splitlines() + if line.startswith('add map ')] + if len(devices) != parts: + msg = 'Surprising number of partitions - check output of losetup -a' + logging.debug("%s", runcmd(['losetup', '-a'])) + logging.debug("%s: devices=%s parts=%s", msg, devices, parts) + raise cliapp.AppException(msg) + root = '/dev/mapper/%s' % devices[rootindex] + if self.settings['bootsize'] or self.settings['use-uefi']: + boot = '/dev/mapper/%s' % devices[bootindex] + if self.settings['swap'] > 0: + swap = '/dev/mapper/%s' % devices[swapindex] + self.devices['rootdev'] = root + self.devices['bootdev'] = boot + self.devices['swap'] = swap + + def mkfs(self, device, fstype): + self.message('Creating filesystem %s' % fstype) + runcmd(['mkfs', '-t', fstype, device]) + + def create_fstab(self): + rootdir = self.devices['rootdir'] + rootdev = self.devices['rootdev'] + bootdev = self.devices['bootdev'] + boottype = self.devices['boottype'] + + def fsuuid(device): + out = runcmd(['blkid', '-c', '/dev/null', '-o', 'value', + '-s', 'UUID', device]) + return out.splitlines()[0].strip() + + if rootdev: + rootdevstr = 'UUID=%s' % fsuuid(rootdev) + else: + rootdevstr = '/dev/sda1' + + if bootdev and not self.settings['use-uefi']: + bootdevstr = 'UUID=%s' % fsuuid(bootdev) + else: + bootdevstr = None + + if not rootdir: + raise cliapp.AppException("rootdir not set") + + fstab = os.path.join(str(rootdir), 'etc', 'fstab') + with open(fstab, 'w') as fstab: + fstab.write('proc /proc proc defaults 0 0\n') + fstab.write('%s / %s errors=remount-ro 0 1\n' % (rootdevstr, roottype)) + if bootdevstr: + fstab.write('%s /boot %s errors=remount-ro 0 2\n' % (bootdevstr, boottype)) + if self.settings['swap'] > 0: + fstab.write("/dev/sda3 swap swap defaults 0 0\n") + elif self.settings['swap'] > 0: + fstab.write("/dev/sda2 swap swap defaults 0 0\n") + + def squash(self): + """ + Run squashfs on the image. + """ + if not self.settings['squash']: + return + if not os.path.exists('/usr/bin/mksquashfs'): + logging.warning("Squash selected but mksquashfs not found!") + return + logging.debug( + "%s usage: %s", self.settings['image'], + runcmd(['du', self.settings['image']])) + self.message("Running mksquashfs") + suffixed = "%s.squashfs" % self.settings['image'] + if os.path.exists(suffixed): + os.unlink(suffixed) + msg = runcmd( + ['mksquashfs', self.settings['image'], + suffixed, + '-no-progress', '-comp', 'xz'], ignore_fail=False) + logging.debug(msg) + check_size = os.path.getsize(suffixed) + if check_size < (1024 * 1024): + logging.warning( + "%s appears to be too small! %s bytes", + suffixed, check_size) + else: + logging.debug("squashed size: %s", check_size) + os.unlink(self.settings['image']) + self.settings['image'] = suffixed + logging.debug( + "%s usage: %s", self.settings['image'], + runcmd(['du', self.settings['image']])) + + def configure_apt(self): + rootdir = self.devices['rootdir'] + if not self.settings['configure-apt'] or not self.settings['apt-mirror']: + return + if not rootdir: + raise cliapp.AppException("rootdir not set") + # use the distribution and mirror to create an apt source + self.message("Configuring apt to use distribution and mirror") + conf = os.path.join(str(rootdir), 'etc', 'apt', 'sources.list.d', 'base.list') + logging.debug('configure apt %s', conf) + mirror = self.settings['mirror'] + if self.settings['apt-mirror']: + mirror = self.settings['apt-mirror'] + self.message("Setting apt mirror to %s" % mirror) + os.unlink(os.path.join(str(rootdir), 'etc', 'apt', 'sources.list')) + source = open(conf, 'w') + line = 'deb %s %s main\n' % (mirror, self.settings['distribution']) + source.write(line) + line = '#deb-src %s %s main\n' % (mirror, self.settings['distribution']) + source.write(line) + source.close() + # ensure the apt sources have valid lists + runcmd(['chroot', rootdir, 'apt-get', '-qq', 'update']) + + def list_installed_pkgs(self): + if not self.settings['pkglist']: + return + rootdir = self.devices['rootdir'] + # output the list of installed packages for sources identification + self.message("Creating a list of installed binary package names") + out = runcmd(['chroot', rootdir, + 'dpkg-query', '-W', "-f='${Package}.deb\n'"]) + with open('dpkg.list', 'w') as dpkg: + dpkg.write(out) + + def remove_udev_persistent_rules(self): + rootdir = self.devices['rootdir'] + if not rootdir: + raise cliapp.AppException("rootdir not set") + self.message('Removing udev persistent cd and net rules') + for x in ['70-persistent-cd.rules', '70-persistent-net.rules']: + pathname = os.path.join(str(rootdir), 'etc', 'udev', 'rules.d', x) + if os.path.exists(pathname): + logging.debug('rm %s', pathname) + os.remove(pathname) + else: + logging.debug('not removing non-existent %s', pathname) + + def set_hostname(self): + rootdir = self.devices['rootdir'] + hostname = self.settings['hostname'] + if not rootdir: + raise cliapp.AppException("rootdir not set") + with open(os.path.join(str(rootdir), 'etc', 'hostname'), 'w') as f: + f.write('%s\n' % hostname) + + etc_hosts = os.path.join(str(rootdir), 'etc', 'hosts') + try: + with open(etc_hosts, 'r') as f: + data = f.read() + with open(etc_hosts, 'w') as f: + for line in data.splitlines(): + if line.startswith('127.0.0.1'): + line += ' %s' % hostname + f.write('%s\n' % line) + except IOError: + pass |