1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
# SPDX-License-Identifier: GPL-3.0-or-later
"""
Base worker class to run various commands that build the image.
"""
import logging
import os
from . import internal, library
BASE_PACKAGES = []
logger = logging.getLogger(__name__) # pylint: disable=invalid-name
class ImageBuilder: # pylint: disable=too-many-instance-attributes
"""Base for all image builders."""
architecture: str | None = None
machine: str = 'all'
include_non_free_firmware: bool = False
include_contrib: bool = False
builder_backend: str = 'internal'
partition_table_type: str = 'msdos'
root_filesystem_type: str = 'btrfs'
boot_filesystem_type: str | None = None
boot_size: str | None = None
efi_filesystem_type: str | None = None
efi_size: str | None = None
firmware_filesystem_type: str | None = None
firmware_size: str | None = None
kernel_flavor: str = 'default'
debootstrap_variant: str | None = None
@classmethod
def get_target_name(cls):
"""Return the command line name of target for this builder."""
return None
@classmethod
def get_builder_class(cls, target):
"""Return an builder class given target name."""
from . import builders # noqa: F401, pylint: disable=unused-variable
for subclass in cls.get_subclasses():
if subclass.get_target_name() == target:
return subclass
raise ValueError('No such target')
@classmethod
def get_subclasses(cls):
"""Iterate through the subclasses of this class."""
for subclass in cls.__subclasses__():
yield subclass
yield from subclass.get_subclasses()
def __init__(self, arguments):
"""Initialize object."""
self.arguments = arguments
self.packages = BASE_PACKAGES
self.ram_directory = None
self.builder_backends = {}
self.builder_backends['internal'] = internal.InternalBuilderBackend(
self)
self.image_file = os.path.join(self.arguments.build_dir,
self._get_image_base_name() + '.img')
@property
def image_size(self):
"""Return the size of the image to create based on CLI arguments."""
return self.arguments.image_size
@property
def release_components(self):
"""Return the Debian release components to use for the build."""
components = ['main']
if self.include_non_free_firmware:
components.append('non-free-firmware')
if self.include_contrib:
components.append('contrib')
if self.arguments.release_component:
for component in self.arguments.release_component:
if component not in components:
components.append(component)
return components
def build(self):
"""Run the image building process."""
archive_file = self.image_file + '.xz'
self.make_image()
self.compress(archive_file, self.image_file)
self.sign(archive_file)
def _get_builder_backend(self):
"""Returns the builder backend."""
builder = self.builder_backend
return self.builder_backends[builder]
def make_image(self):
"""Call a builder backend to create basic image."""
self._get_builder_backend().make_image()
def _get_image_base_name(self):
"""Return the base file name of the final image."""
build_stamp = self.arguments.build_stamp
build_stamp = build_stamp + '_' if build_stamp else ''
return 'freedombox-{distribution}_{build_stamp}{machine}' \
'-{architecture}'.format(
distribution=self.arguments.distribution,
build_stamp=build_stamp, machine=self.machine,
architecture=self.architecture)
def compress(self, archive_file, image_file):
"""Compress the generated image."""
if not self.arguments.skip_compression:
library.compress(archive_file, image_file)
else:
logger.info('Skipping image compression')
def sign(self, archive):
"""Sign the final output image."""
if not self.arguments.sign:
return
library.sign(archive)
@staticmethod
def _replace_extension(file_name, new_extension):
"""Replace a file's extension with a new extention."""
return file_name.rsplit('.', maxsplit=1)[0] + new_extension
|