diff options
-rwxr-xr-x | bin/vmdebootstrap | 23 | ||||
-rw-r--r-- | doc/live.rst | 10 | ||||
-rw-r--r-- | man/vmdebootstrap.rst | 28 | ||||
-rw-r--r-- | vmdebootstrap/filesystem.py | 69 |
4 files changed, 52 insertions, 78 deletions
diff --git a/bin/vmdebootstrap b/bin/vmdebootstrap index 1b788d3..c44ff25 100755 --- a/bin/vmdebootstrap +++ b/bin/vmdebootstrap @@ -166,13 +166,9 @@ class VmDebootstrap(cliapp.Application): # pylint: disable=too-many-public-meth self.settings.string( ['owner'], 'the user who will own the image when ' 'the build is complete.') - self.settings.boolean( - ['squash'], 'use squashfs on the final image.') self.settings.string( - ['squash-file'], 'filename for the squashfs ' - '- cannot be used with --image', - metavar='FILE', - default='rootfs.squash') + ['squash'], 'use squashfs on the rootfs - ' + 'cannot be used with --image', metavar='DIRECTORY') self.settings.boolean( ['configure-apt'], 'Create an apt source based on ' 'the distribution and mirror selected.') @@ -198,6 +194,9 @@ class VmDebootstrap(cliapp.Application): # pylint: disable=too-many-public-meth handler.define_settings(self.settings) distro = self.handlers[Codenames.name] + if self.settings['squash'] and self.settings['image']: + raise cliapp.AppException( + '--image can no longer be used with --squash') if not self.settings['image'] and not ( self.settings['tarball'] or self.settings['squash']): raise cliapp.AppException( @@ -279,7 +278,6 @@ class VmDebootstrap(cliapp.Application): # pylint: disable=too-many-public-meth extlinux.install_extlinux(rootdev, rootdir) base.append_serial_console(rootdir) self.optimize_image(rootdir) - filesystem.squash_image() def start_ops(self): base = self.handlers[Base.name] @@ -291,6 +289,7 @@ class VmDebootstrap(cliapp.Application): # pylint: disable=too-many-public-meth rootdev = filesystem.devices['rootdev'] else: rootdir = self.mkdtemp() + filesystem.devices['rootdir'] = rootdir rootdev = filesystem.devices['rootdev'] logging.debug("rootdir=%s rootdev=%s", rootdir, rootdev) self.debootstrap(rootdir) @@ -315,9 +314,13 @@ class VmDebootstrap(cliapp.Application): # pylint: disable=too-many-public-meth if self.settings['tarball']: base.create_tarball(rootdir) - else: - filesystem.squash_filesystem() + elif self.settings['squash']: + filesystem.squash_rootfs() filesystem.chown() + # need to copy boot/efi/* if configured. + # but that is a task for the uefi module. + # if self.settings['use-uefi'] and self.settings['squash']: + # export uefi files except BaseException as e: base.message('EEEK! Something bad happened...') @@ -326,6 +329,8 @@ class VmDebootstrap(cliapp.Application): # pylint: disable=too-many-public-meth db_log = os.path.join(rootdir, 'debootstrap', 'debootstrap.log') if os.path.exists(db_log): shutil.copy(db_log, os.getcwd()) + if self.settings['owner']: + runcmd(["chown", self.settings["owner"], db_log]) base.message(e) self.cleanup_system() raise diff --git a/doc/live.rst b/doc/live.rst index 002072c..0106de9 100644 --- a/doc/live.rst +++ b/doc/live.rst @@ -87,10 +87,6 @@ Initial schemes for vmdebootstrap creation of live images customisation hook, remove that source and replace the original. #. ``mksquashfs`` can fail without indication of why and when it does, the image - file can be 4Kb or so of junk. To prevent this, avoid running - vmdebootstrap with the ``--squash`` option and run mksquashfs as a second step - **after** copying the raw image to a new file for safety / debugging. - Newer versions of vmdebootstrap will emit a warning and not delete - the original file if the squashfs output is less than 1MB. This can - occur if the drive runs out of space but squashfs does not report - an error. + file can be 4Kb or so of junk. ``vmdebootstrap`` will fail if the + squashfs output is less than 1MB. This can occur if the drive runs + out of space but squashfs does not report an error. diff --git a/man/vmdebootstrap.rst b/man/vmdebootstrap.rst index 74bb153..90fad4c 100644 --- a/man/vmdebootstrap.rst +++ b/man/vmdebootstrap.rst @@ -107,23 +107,19 @@ Options Useful for architectures where extlinux is not supportable. Depending on how the image is to be booted, the --mbr option may also be necessary with extlinux. - --squash Run mksquashfs against the final image using xz + --squash=DIRECTORY Run mksquashfs against the rootfs using xz compression - requires ``squashfs-tools`` to be installed. - The final file will have the ``.squashfs`` suffix. - By default, mksquashfs is allowed to use all processors - which may result in high load. Run ``mksquashfs`` - separately if you need to control the number of - processors used per run. squashfs can also have issues - with large image files (where large is a factor of the - amount of data inside the image rather than the size - of the image itself). These errors can result in invalid - images (e.g. image does not boot) or corrupted images - (truncated file). This is a known bug in squashfs. - Avoid using the --squash option and consider squashing - the loopback mounted directory tree of the image. - ``vmdebootstrap`` will check if the squashed filesystem - is less than 1MB and leave the unsquashed image in - place with a warning about a possible squashfs failure. + The squashfs and other files needed to use the squashfs + to make a bootable system will be put into the specified directory. + The directory will contain a ``filesystem.squashfs`` + as well as the top level contents of the ``boot/`` + directory. (If using UEFI, the ``boot/efi`` directory + as well.) By default, ``mksquashfs`` is allowed to use + all processors which may result in high load. squashfs + can also have issues with large root filesystems. These + errors can result in truncated files. This is a known + bug in squashfs. ``vmdebootstrap`` will fail if the + squashed filesystem is less than 1MB. --configure-apt Use the specified mirror and distribution to create a suitable apt source inside the VM. Can be useful if debootstrap fails to create it automatically. diff --git a/vmdebootstrap/filesystem.py b/vmdebootstrap/filesystem.py index 796f7d8..23c7fef 100644 --- a/vmdebootstrap/filesystem.py +++ b/vmdebootstrap/filesystem.py @@ -22,9 +22,9 @@ import os +import shutil import cliapp import logging -import subprocess from vmdebootstrap.base import Base, runcmd # pylint: disable=missing-docstring @@ -58,10 +58,12 @@ class Filesystem(Base): filename = self.settings['image'] elif self.settings['tarball']: filename = self.settings['tarball'] + elif self.settings['squash']: + filename = self.settings['squash'] else: return self.message("Changing owner to %s" % self.settings["owner"]) - subprocess.call(["chown", self.settings["owner"], filename]) + runcmd(["chown", "-R", self.settings["owner"], filename]) def update_initramfs(self): rootdir = self.devices['rootdir'] @@ -160,69 +162,44 @@ class Filesystem(Base): elif self.settings['swap'] > 0: fstab.write("/dev/sda2 swap swap defaults 0 0\n") - def squash_filesystem(self): + def squash_rootfs(self): """ - Run squashfs on the temporary directory - """ - if not self.settings['squash']: - return - if self.settings['image']: - 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") - output = self.settings['squash-file'] - if os.path.exists(output): - os.unlink(output) - msg = runcmd( - ['mksquashfs', self.devices['rootdir'], - output, '-no-progress', '-comp', 'xz'], ignore_fail=False) - logging.debug(msg) - check_size = os.path.getsize(output) - if check_size < (1024 * 1024): - logging.warning( - "%s appears to be too small! %s bytes", - output, check_size) - else: - logging.debug("squashed size: %s", check_size) - - def squash_image(self): - """ - Run squashfs on the image. + Run squashfs on the rootfs within the image. + Copy the initrd and the kernel out, squashfs the rest. + Also UEFI files, if enabled, ESP partition as a vfat image. TBD. """ 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 not os.path.exists(self.settings['squash']): + os.mkdir(self.settings['squash']) + suffixed = os.path.join(self.settings['squash'], "filesystem.squashfs") if os.path.exists(suffixed): os.unlink(suffixed) + self.message("Running mksquashfs on rootfs.") msg = runcmd( - ['mksquashfs', self.settings['image'], - suffixed, + ['mksquashfs', self.devices['rootdir'], suffixed, '-no-progress', '-comp', 'xz'], ignore_fail=False) logging.debug(msg) check_size = os.path.getsize(suffixed) + logging.debug("Created squashfs: %s" % 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']])) + bootdir = os.path.join(self.devices['rootdir'], 'boot') + # copying the boot/* files + self.message("Copying boot files out of squashfs") + for filename in os.listdir(bootdir): + if os.path.isdir(filename) or os.path.islink(filename): + continue + shutil.copyfile( + os.path.join(bootdir, filename), + os.path.join(self.settings['squash'], filename)) def configure_apt(self): rootdir = self.devices['rootdir'] |