Source code for dockeroo.docker.gentoo_diskimage


# -*- coding: utf-8 -*-
#
# Copyright (c) 2016, Giacomo Cariello. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import os

from dockeroo import BaseGroupRecipe
from dockeroo.docker import BaseDockerSubRecipe
from dockeroo.utils import string_as_bool


class GentooDiskImageSubRecipe(BaseDockerSubRecipe): # pylint: disable=too-many-instance-attributes

    def initialize(self):
        super(GentooDiskImageSubRecipe, self).initialize()

        self.build_command = self.options.get('build-command', "/bin/freeze")
        self.build_container = "{}_build".format(self.name)
        self.build_image = self.options['build-image']
        self.build_volumes_from = self.options.get('build-volumes-from', None)
        self.build_script_user = self.options.get('build-script-user', None)
        self.build_script_shell = self.options.get(
            'build-script-shell', self.shell)
        self.prepare_script = "#!{}\n{}".format(
            self.build_script_shell, '\n'.join(
                [_f for _f in
                 [x.strip() for x in
                  self.options.get('prepare-script').replace('$$', '$').splitlines()]
                 if _f])) if self.options.get('prepare-script', None) is not None else None
        self.build_script = "#!{}\n{}".format(
            self.build_script_shell, '\n'.join(
                [_f for _f in
                 [x.strip() for x in
                  self.options.get('build-script').replace('$$', '$').splitlines()]
                 if _f])) if self.options.get('build-script', None) is not None else None
        self.build_root = self.options['build-root']
        self.base_image = self.options['base-image']
        self.image_file = self.options['image-file']

        self.platform = self.options.get('platform', self.engine.platform)
        self.arch = self.options.get('arch', self.platform)
        self.tty = string_as_bool(self.options.get('tty', False))

    def install(self):
        self.location = self.options.get("location", os.path.join(
            self.buildout["buildout"]["parts-directory"], self.name))
        self.engine.remove_container(self.build_container)
        self.engine.create_container(self.build_container, self.build_image,
                                     command=self.build_command,
                                     privileged=True, tty=self.tty,
                                     volumes_from=self.build_volumes_from)
        self.engine.start_container(self.build_container)
        if self.platform != self.engine.platform:
            self.engine.config_binfmt(self.build_container, self.platform)
        if self.prepare_script:
            self.engine.run_script(self.build_container, self.prepare_script,
                                   shell=self.build_script_shell,
                                   user=self.build_script_user)
        self.engine.copy_image_to_container(
            self.base_image, self.build_container, "/", dst=self.build_root)
        if self.build_script:
            self.engine.run_script(self.build_container, self.build_script,
                                   shell=self.build_script_shell,
                                   user=self.build_script_user)
        self.engine.export_files(self.build_container, self.image_file, self.location)
        self.engine.remove_container(self.build_container)
        self.engine.clean_stale_images()
        return self.mark_completed()

    def update(self):
        if self.is_image_updated(self.build_image) or \
                self.is_image_updated(self.base_image):
            return self.install()
        else:
            return (self.completed, )

    def uninstall(self):
        self.engine.remove_container(self.build_container)


[docs]class DockerGentooDiskImageRecipe(BaseGroupRecipe): """ This recipe executes the following tasks: 1. Creates a temporary container from **builder-image** docker image. 2. Executes **prepare-script** on the builder container. 3. Extracts **base-image** docker image into **build-root** folder. 4. Executes **build-script** on the builder container. 5. Extracts **image-file** from the builder container and saves it into **${:location}**. .. describe:: Usage The following example buildout part shows how to build a linux disk image from a **base** image using a **builder** image produced with :py:class:`dockeroo.docker.gentoo_bootstrap.DockerGentooBootstrapRecipe`. .. code-block:: ini [disk-image] recipe = dockeroo:docker.gentoo-diskimage build-image = builder:latest base-image = base:latest build-root = /mnt/ image-file = /tmp/disk.img prepare-script = mkdir -p /tmp && dd if=/dev/zero of=${:image-file} bs=1M count=2048 parted -a optimal ${:image-file} mklabel msdos parted -a optimal ${:image-file} unit mib mkpart primary fat32 1 131 parted -a optimal ${:image-file} set 1 boot on parted -a optimal ${:image-file} unit mib mkpart primary linux-swap 131 643 parted -a optimal ${:image-file} unit mib mkpart primary ext2 643 100% rm -f /dev/loop0; mknod /dev/loop0 b 7 0 rm -f /dev/loop0p1 rm -f /dev/loop0p2 rm -f /dev/loop0p3 losetup --show -P /dev/loop0 ${:image-file} mknod /dev/loop0p1 b 259 0 mknod /dev/loop0p2 b 259 1 mknod /dev/loop0p3 b 259 2 mkfs.vfat -F 32 -n BOOT /dev/loop0p1 mkswap /dev/loop0p2 mkfs.ext4 -T small /dev/loop0p3 mount -t ext4 /dev/loop0p3 /mnt mkdir -p /mnt/boot mount -t vfat /dev/loop0p1 /mnt/boot build-script = umount /dev/loop0p1 umount /dev/loop0p3 losetup -d /dev/loop0 >/dev/null 2>&1 .. describe:: Configuration options This recipe accepts the following options: base-image Docker image to use as base for disk creation. build-command Command to launch on builder container upon creation. Defaults to "/bin/freeze". build-image Docker image to use as builder. build-root Root folder where **base-image** is extracted. build-script This shell script is executed after **base-image** extraction. build-script-shell Shell to use for script execution. Defaults to "/bin/sh". build-script-user User which executes the **prepare-script** and **build-script**. If unset, docker default is applied. build-volumes-from Volumes to be mounted on build container upon creation. image-file Disk image file which is extracted from build container. location Path where disk image will be saved. Defaults to ${buildout:parts-directory}/${:name}. machine-name Docker machine where **build-image** and **base-image** reside. Defaults to DOCKER_MACHINE_NAME environment variable or "default" if unset. prepare-script This shell script is executed before **base-image** extraction. timeout **docker** command timeout. """ subrecipe_class = GentooDiskImageSubRecipe