diff --git a/223abea7c4c1fd2871956c61de607682d2409a1e.patch b/223abea7c4c1fd2871956c61de607682d2409a1e.patch
new file mode 100644
index 0000000000000000000000000000000000000000..65e6476cf26eb587f383ea2432fc70f2bf84bb0f
--- /dev/null
+++ b/223abea7c4c1fd2871956c61de607682d2409a1e.patch
@@ -0,0 +1,475 @@
+diff --git a/kiwi/package_manager/apt.py b/kiwi/package_manager/apt.py
+index 5fc9ea00f6..24146f08d1 100644
+--- a/kiwi/package_manager/apt.py
++++ b/kiwi/package_manager/apt.py
+@@ -20,9 +20,7 @@
+ import logging
+
+ # project
+-from kiwi.defaults import Defaults
+ from kiwi.command import Command
+-from kiwi.utils.sync import DataSync
+ from kiwi.path import Path
+ from kiwi.package_manager.base import PackageManagerBase
+ from kiwi.exceptions import (
+@@ -106,13 +104,16 @@ def request_package_exclusion(self, name):
+ 'Package exclusion for (%s) not supported for apt-get', name
+ )
+
+- def process_install_requests_bootstrap(self):
++ def process_install_requests_bootstrap(self, root_bind=None):
+ """
+ Process package install requests for bootstrap phase (no chroot)
+ The debootstrap program is used to bootstrap a new system with
+ a collection of predefined packages. The kiwi bootstrap section
+ information is not used in this case
+
++ :param object root_bind: instance of RootBind to manage kernel
++ file systems before debootstrap call
++
+ :raises KiwiDebootstrapError: if no main distribution repository
+ is configured, if the debootstrap script is not found or if the
+ debootstrap script execution fails
+@@ -130,7 +131,17 @@ def process_install_requests_bootstrap(self):
+ 'debootstrap script for %s distribution not found' %
+ self.distribution
+ )
+- bootstrap_dir = self.root_dir + '.debootstrap'
++
++ # APT package manager does not support bootstrapping. To circumvent
++ # this limitation there is the debootstrap tool for APT based distros.
++ # Because of that there is a little overlap between KIWI and
++ # debootstrap. Debootstrap manages itself the kernel file systems for
++ # chroot environment, thus we need to umount the kernel file systems
++ # before calling debootstrap and remount them afterwards.
++ root_bind.umount_kernel_file_systems()
++ # debootsrap will create its own dev/fd device
++ os.unlink(os.path.normpath(os.sep.join([self.root_dir, 'dev/fd'])))
++
+ if 'apt-get' in self.package_requests:
+ # debootstrap takes care to install apt-get
+ self.package_requests.remove('apt-get')
+@@ -143,31 +154,36 @@ def process_install_requests_bootstrap(self):
+ cmd.append('--no-check-gpg')
+ if self.deboostrap_minbase:
+ cmd.append('--variant=minbase')
++ if self.package_requests:
++ cmd.append(
++ '--include={}'.format(','.join(self.package_requests))
++ )
+ if self.repository.components:
+ cmd.append(
+ '--components={0}'.format(
+ ','.join(self.repository.components)
+ )
+ )
++ self.cleanup_requests()
+ cmd.extend([
+- self.distribution, bootstrap_dir, self.distribution_path
++ self.distribution, self.root_dir, self.distribution_path
+ ])
+- Command.run(cmd, self.command_env)
+- data = DataSync(
+- bootstrap_dir + '/', self.root_dir
+- )
+- data.sync_data(
+- options=Defaults.get_sync_options(),
+- exclude=['proc', 'sys', 'dev']
+- )
++
++ return Command.call(cmd, self.command_env)
+ except Exception as e:
+ raise KiwiDebootstrapError(
+ '%s: %s' % (type(e).__name__, format(e))
+ )
+- finally:
+- Path.wipe(bootstrap_dir)
+
+- return self.process_install_requests()
++ def post_process_install_requests_bootstrap(self, root_bind=None):
++ """
++ Mounts the kernel file systems to the chroot environment is
++ ready after the bootstrap procedure
++
++ :param object root_bind: instance of RootBind to manage kernel
++ file systems
++ """
++ root_bind.mount_kernel_file_systems()
+
+ def process_install_requests(self):
+ """
+diff --git a/kiwi/package_manager/base.py b/kiwi/package_manager/base.py
+index 470a64d8b5..50c6c63d17 100644
+--- a/kiwi/package_manager/base.py
++++ b/kiwi/package_manager/base.py
+@@ -98,7 +98,7 @@ def request_package_exclusion(self, name):
+ """
+ raise NotImplementedError
+
+- def process_install_requests_bootstrap(self):
++ def process_install_requests_bootstrap(self, root_bind=None):
+ """
+ Process package install requests for bootstrap phase (no chroot)
+
+@@ -182,7 +182,7 @@ def dump_reload_package_database(self, version=45):
+ """
+ pass
+
+- def post_process_install_requests_bootstrap(self):
++ def post_process_install_requests_bootstrap(self, root_bind=None):
+ """
+ Process extra code required after bootstrapping
+
+diff --git a/kiwi/package_manager/dnf.py b/kiwi/package_manager/dnf.py
+index 2ed5921a68..d082fb669c 100644
+--- a/kiwi/package_manager/dnf.py
++++ b/kiwi/package_manager/dnf.py
+@@ -84,10 +84,12 @@ def request_package_exclusion(self, name):
+ """
+ self.exclude_requests.append(name)
+
+- def process_install_requests_bootstrap(self):
++ def process_install_requests_bootstrap(self, root_bind=None):
+ """
+ Process package install requests for bootstrap phase (no chroot)
+
++ :param object root_bind: unused
++
+ :return: process results in command type
+
+ :rtype: namedtuple
+@@ -258,10 +260,12 @@ def match_package_deleted(self, package_name, dnf_output):
+ '.*Removing: ' + re.escape(package_name) + '.*', dnf_output
+ )
+
+- def post_process_install_requests_bootstrap(self):
++ def post_process_install_requests_bootstrap(self, root_bind=None):
+ """
+ Move the rpm database to the place as it is expected by the
+ rpm package installed during bootstrap phase
++
++ :param object root_bind: unused
+ """
+ rpmdb = RpmDataBase(self.root_dir)
+ if rpmdb.has_rpm():
+diff --git a/kiwi/package_manager/pacman.py b/kiwi/package_manager/pacman.py
+index 3fc82a2fba..6a85e6b66a 100644
+--- a/kiwi/package_manager/pacman.py
++++ b/kiwi/package_manager/pacman.py
+@@ -94,10 +94,12 @@ def request_package_exclusion(self, name):
+ """
+ self.exclude_requests.append(name)
+
+- def process_install_requests_bootstrap(self):
++ def process_install_requests_bootstrap(self, root_bind=None):
+ """
+ Process package install requests for bootstrap phase (no chroot)
+
++ :param object root_binf: unused
++
+ :return: process results in command type
+
+ :rtype: namedtuple
+diff --git a/kiwi/package_manager/zypper.py b/kiwi/package_manager/zypper.py
+index b67b59c16f..0af6f05608 100644
+--- a/kiwi/package_manager/zypper.py
++++ b/kiwi/package_manager/zypper.py
+@@ -97,10 +97,12 @@ def request_package_exclusion(self, name):
+ """
+ self.exclude_requests.append(name)
+
+- def process_install_requests_bootstrap(self):
++ def process_install_requests_bootstrap(self, root_bind=None):
+ """
+ Process package install requests for bootstrap phase (no chroot)
+
++ :param object root_bind: unused
++
+ :return: process results in command type
+
+ :rtype: namedtuple
+diff --git a/kiwi/system/prepare.py b/kiwi/system/prepare.py
+index 54601fb036..91483fa0f0 100644
+--- a/kiwi/system/prepare.py
++++ b/kiwi/system/prepare.py
+@@ -219,7 +219,7 @@ def install_bootstrap(self, manager, plus_packages=None):
+ bootstrap_products
+ )
+ process = CommandProcess(
+- command=manager.process_install_requests_bootstrap(),
++ command=manager.process_install_requests_bootstrap(self.root_bind),
+ log_topic='bootstrap'
+ )
+ try:
+@@ -237,7 +237,7 @@ def install_bootstrap(self, manager, plus_packages=None):
+ reason=issue
+ )
+ )
+- manager.post_process_install_requests_bootstrap()
++ manager.post_process_install_requests_bootstrap(self.root_bind)
+ # process archive installations
+ if bootstrap_archives:
+ try:
+diff --git a/kiwi/system/root_bind.py b/kiwi/system/root_bind.py
+index b72c5ff6e6..f67b2f24c7 100644
+--- a/kiwi/system/root_bind.py
++++ b/kiwi/system/root_bind.py
+@@ -98,6 +98,19 @@ def mount_kernel_file_systems(self):
+ '%s: %s' % (type(e).__name__, format(e))
+ )
+
++ def umount_kernel_file_systems(self):
++ """
++ Umount kernel filesystems
++
++ :raises KiwiMountKernelFileSystemsError: if some kernel filesystem
++ fails to mount
++ """
++ umounts = [
++ mnt for mnt in self.mount_stack if mnt.device
++ in self.bind_locations
++ ]
++ self._cleanup_mounts(umounts)
++
+ def mount_shared_directory(self, host_dir=None):
+ """
+ Bind mount shared location
+@@ -266,19 +279,22 @@ def _restore_intermediate_config_rpmnew_variants(self):
+
+ shutil.move(config_rpm_new, self.root_dir + config)
+
+- def _cleanup_mount_stack(self):
+- for mount in reversed(self.mount_stack):
+- if mount.is_mounted():
++ def _cleanup_mounts(self, umounts):
++ for umount in reversed(umounts):
++ if umount.is_mounted():
+ try:
+- mount.umount_lazy()
++ umount.umount_lazy()
++ self.mount_stack.remove(umount)
+ except Exception as e:
+ log.warning(
+ 'Image root directory %s not cleanly umounted: %s',
+ self.root_dir, format(e)
+ )
+ else:
+- log.warning('Path %s not a mountpoint', mount.mountpoint)
++ log.warning('Path %s not a mountpoint', umount.mountpoint)
+
++ def _cleanup_mount_stack(self):
++ self._cleanup_mounts(self.mount_stack)
+ del self.mount_stack[:]
+
+ def _cleanup_dir_stack(self):
+diff --git a/test/unit/package_manager/apt_test.py b/test/unit/package_manager/apt_test.py
+index ad78f459f9..e6873ce680 100644
+--- a/test/unit/package_manager/apt_test.py
++++ b/test/unit/package_manager/apt_test.py
+@@ -1,7 +1,5 @@
+ import logging
+-from mock import (
+- patch, call
+-)
++from mock import patch
+ from pytest import (
+ raises, fixture
+ )
+@@ -70,102 +68,74 @@ def test_process_install_requests_bootstrap_no_debootstrap_script(
+ with raises(KiwiDebootstrapError):
+ self.manager.process_install_requests_bootstrap()
+
+- @patch('kiwi.command.Command.run')
+- @patch('os.path.exists')
++ @patch('kiwi.command.Command.call')
++ @patch('kiwi.package_manager.apt.os.path.exists')
++ @patch('kiwi.package_manager.apt.os.unlink')
+ @patch('kiwi.package_manager.apt.Path.wipe')
+ def test_process_install_requests_bootstrap_failed_debootstrap(
+- self, mock_wipe, mock_exists, mock_run
++ self, mock_wipe, mock_unlink, mock_exists, mock_call
+ ):
+ self.manager.request_package('apt-get')
+- mock_run.side_effect = Exception
++ mock_call.side_effect = Exception
+ mock_exists.return_value = True
++ mock_root_bind = mock.Mock()
+ with raises(KiwiDebootstrapError):
+- self.manager.process_install_requests_bootstrap()
++ self.manager.process_install_requests_bootstrap(mock_root_bind)
+
+ @patch('kiwi.command.Command.call')
+- @patch('kiwi.command.Command.run')
+- @patch('os.path.exists')
+- @patch('kiwi.package_manager.apt.DataSync')
++ @patch('kiwi.package_manager.apt.os.unlink')
++ @patch('kiwi.package_manager.apt.os.path.exists')
+ def test_process_install_requests_bootstrap(
+- self, mock_sync, mock_exists, mock_run, mock_call
++ self, mock_exists, mock_unlink, mock_call
+ ):
+ self.manager.request_package('apt-get')
+ self.manager.request_package('vim')
+- data = mock.Mock()
+- mock_sync.return_value = data
++ call_result = mock.Mock()
++ call_result.process.communicate.return_value = ('stdout', 'stderr')
++ mock_call.return_value = call_result
++ mock_root_bind = mock.Mock()
+ mock_exists.return_value = True
+- self.manager.process_install_requests_bootstrap()
+- mock_sync.assert_called_once_with(
+- 'root-dir.debootstrap/', 'root-dir'
+- )
+- data.sync_data.assert_called_once_with(
+- options=['-a', '-H', '-X', '-A', '--one-file-system', '--inplace'],
+- exclude=['proc', 'sys', 'dev']
+- )
+- assert mock_run.call_args_list == [
+- call(
+- [
+- 'debootstrap', '--keyring=trusted.gpg',
+- '--variant=minbase', '--components=main,restricted',
+- 'xenial', 'root-dir.debootstrap', 'xenial_path'
+- ], ['env']
+- ),
+- call(
+- ['rm', '-r', '-f', 'root-dir.debootstrap']
+- ),
+- call(
+- [
+- 'chroot', 'root-dir', 'apt-get',
+- '-c', 'apt.conf', '-y', 'update'
+- ], ['env']
+- )
+- ]
+- mock_call.assert_called_once_with([
+- 'chroot', 'root-dir', 'apt-get',
+- '-c', 'apt.conf', '-y', 'install', 'vim'],
+- ['env']
++ self.manager.process_install_requests_bootstrap(mock_root_bind)
++ mock_call.assert_called_once_with(
++ [
++ 'debootstrap', '--keyring=trusted.gpg',
++ '--variant=minbase', '--include=vim',
++ '--components=main,restricted', 'xenial',
++ 'root-dir', 'xenial_path'
++ ], ['env']
+ )
++ mock_unlink.assert_called_once_with('root-dir/dev/fd')
++ mock_root_bind.umount_kernel_file_systems.assert_called_once_with()
++
++ def test_post_process_install_requests_bootstrap(self):
++ mock_root_bind = mock.Mock()
++ self.manager.post_process_install_requests_bootstrap(mock_root_bind)
++ mock_root_bind.mount_kernel_file_systems.assert_called_once_with()
+
+ @patch('kiwi.command.Command.call')
+- @patch('kiwi.command.Command.run')
+- @patch('os.path.exists')
+- @patch('kiwi.package_manager.apt.DataSync')
++ @patch('kiwi.package_manager.apt.os.unlink')
++ @patch('kiwi.package_manager.apt.os.path.exists')
+ def test_process_install_requests_bootstrap_no_gpg_check(
+- self, mock_sync, mock_exists, mock_run, mock_call
++ self, mock_exists, mock_unlink, mock_call
+ ):
+ self.manager.request_package('apt-get')
+ self.manager.request_package('vim')
+- data = mock.Mock()
+- mock_sync.return_value = data
++ call_result = mock.Mock()
++ call_result.process.communicate.return_value = ('stdout', 'stderr')
++ mock_root_bind = mock.Mock()
++ mock_call.return_value = call_result
+ mock_exists.side_effect = lambda x: True if 'xenial' in x else False
+- self.manager.process_install_requests_bootstrap()
+- mock_sync.assert_called_once_with(
+- 'root-dir.debootstrap/', 'root-dir'
+- )
+- data.sync_data.assert_called_once_with(
+- options=['-a', '-H', '-X', '-A', '--one-file-system', '--inplace'],
+- exclude=['proc', 'sys', 'dev']
+- )
+- assert mock_run.call_args_list == [
+- call(
+- [
+- 'debootstrap', '--no-check-gpg',
+- '--variant=minbase', '--components=main,restricted',
+- 'xenial', 'root-dir.debootstrap', 'xenial_path'
+- ], ['env']
+- ),
+- call(
+- [
+- 'chroot', 'root-dir', 'apt-get',
+- '-c', 'apt.conf', '-y', 'update'
+- ], ['env']
+- )
+- ]
+- mock_call.assert_called_once_with([
+- 'chroot', 'root-dir', 'apt-get',
+- '-c', 'apt.conf', '-y', 'install', 'vim'],
+- ['env']
++ self.manager.process_install_requests_bootstrap(mock_root_bind)
++ mock_call.assert_called_once_with(
++ [
++ 'debootstrap', '--no-check-gpg',
++ '--variant=minbase', '--include=vim',
++ '--components=main,restricted', 'xenial',
++ 'root-dir', 'xenial_path'
++ ], ['env']
+ )
++ mock_unlink.assert_called_once_with('root-dir/dev/fd')
++ mock_root_bind.umount_kernel_file_systems.assert_called_once_with()
+
+ @patch('kiwi.command.Command.call')
+ @patch('kiwi.command.Command.run')
+diff --git a/test/unit/system/prepare_test.py b/test/unit/system/prepare_test.py
+index ff21260c10..8d1ef9cdac 100644
+--- a/test/unit/system/prepare_test.py
++++ b/test/unit/system/prepare_test.py
+@@ -291,12 +291,15 @@ def test_install_bootstrap(
+ 'kiwi'
+ )
+ self.manager.process_install_requests_bootstrap.assert_called_once_with(
++ self.system.root_bind
+ )
+ mock_tar.assert_called_once_with(
+ '{0}/bootstrap.tgz'.format(self.description_dir)
+ )
+ tar.extract.assert_called_once_with('root_dir')
+- self.manager.post_process_install_requests_bootstrap.assert_called_once_with()
++ self.manager.post_process_install_requests_bootstrap.assert_called_once_with(
++ self.system.root_bind
++ )
+
+ @patch('kiwi.xml_state.XMLState.get_bootstrap_packages_sections')
+ def test_install_bootstrap_skipped(self, mock_bootstrap_section):
+diff --git a/test/unit/system/root_bind_test.py b/test/unit/system/root_bind_test.py
+index 6c5db22c70..6c55cf2955 100644
+--- a/test/unit/system/root_bind_test.py
++++ b/test/unit/system/root_bind_test.py
+@@ -94,6 +94,23 @@ def test_mount_kernel_file_systems(self, mock_mount, mock_exists):
+ )
+ shared_mount.bind_mount.assert_called_once_with()
+
++ @patch('kiwi.system.root_bind.MountManager')
++ def test_umount_kernel_file_systems(self, mock_mount):
++ self.mount_manager.device = '/proc'
++ self.mount_manager.is_mounted = Mock(return_value=True)
++ self.bind_root.umount_kernel_file_systems()
++ self.mount_manager.umount_lazy.assert_called_once_with()
++ assert self.bind_root.mount_stack == []
++
++ @patch('kiwi.system.root_bind.MountManager')
++ def test_umount_kernel_file_systems_raises_error(self, mock_mount):
++ self.mount_manager.device = '/proc'
++ self.mount_manager.is_mounted = Mock(return_value=True)
++ self.mount_manager.umount_lazy = Mock(side_effect=Exception)
++ self.bind_root.umount_kernel_file_systems()
++ self.mount_manager.umount_lazy.assert_called_once_with()
++ assert self.bind_root.mount_stack == [self.mount_manager]
++
+ @patch('kiwi.system.root_bind.MountManager')
+ @patch('kiwi.system.root_bind.Path.create')
+ def test_mount_shared_directory(self, mock_path, mock_mount):
diff --git a/36003143223010c629755b3a24e616f7c66b1f5f.patch b/36003143223010c629755b3a24e616f7c66b1f5f.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2e28b24ac8fb5513eb92b5a8c93ad8d9383fbdda
--- /dev/null
+++ b/36003143223010c629755b3a24e616f7c66b1f5f.patch
@@ -0,0 +1,1037 @@
+diff --git a/kiwi/builder/disk.py b/kiwi/builder/disk.py
+index 6d9058e71d..d763af2680 100644
+--- a/kiwi/builder/disk.py
++++ b/kiwi/builder/disk.py
+@@ -548,7 +548,7 @@ def create_disk_format(self, result_instance):
+ """
+ if self.image_format:
+ log.info('Creating %s Disk Format', self.image_format)
+- disk_format = DiskFormat(
++ disk_format = DiskFormat.new(
+ self.image_format, self.xml_state,
+ self.root_dir, self.target_dir
+ )
+@@ -566,7 +566,7 @@ def append_unpartitioned_space(self):
+ 'Expanding disk with %d bytes of unpartitioned space',
+ self.unpartitioned_bytes
+ )
+- disk_format = DiskFormat(
++ disk_format = DiskFormat.new(
+ 'raw', self.xml_state, self.root_dir, self.target_dir
+ )
+ disk_format.resize_raw_disk(self.unpartitioned_bytes, append=True)
+diff --git a/kiwi/solver/repository/__init__.py b/kiwi/solver/repository/__init__.py
+index 465f357ecc..41f1ec6cfc 100644
+--- a/kiwi/solver/repository/__init__.py
++++ b/kiwi/solver/repository/__init__.py
+@@ -15,29 +15,45 @@
+ # You should have received a copy of the GNU General Public License
+ # along with kiwi. If not, see
+ #
+-# project
+-from kiwi.solver.repository.suse import SolverRepositorySUSE
+-from kiwi.solver.repository.rpm_md import SolverRepositoryRpmMd
+-from kiwi.solver.repository.rpm_dir import SolverRepositoryRpmDir
++import importlib
++from abc import (
++ ABCMeta,
++ abstractmethod
++)
+
++# project
+ from kiwi.exceptions import KiwiSolverRepositorySetupError
+
+
+-class SolverRepository:
++class SolverRepository(metaclass=ABCMeta):
+ """
+ **Repository factory for creation of SAT solvables**
+
+ * :param object uri: Instance of :class:`Uri`
+ """
+- def __new__(self, uri, user=None, secret=None):
+- if uri.repo_type == 'yast2':
+- return SolverRepositorySUSE(uri, user, secret)
+- elif uri.repo_type == 'rpm-md':
+- return SolverRepositoryRpmMd(uri, user, secret)
+- elif uri.repo_type == 'rpm-dir':
+- return SolverRepositoryRpmDir(uri, user, secret)
+- else:
++ @abstractmethod
++ def __init__(self) -> None:
++ return None # pragma: no cover
++
++ @staticmethod
++ def new(uri: object, user: str=None, secret: str=None): # noqa: E252
++ name_map = {
++ 'yast2': ['SolverRepositorySUSE', 'suse'],
++ 'rpm-md': ['SolverRepositoryRpmMd', 'rpm_md'],
++ 'rpm-dir': ['SolverRepositoryRpmDir', 'rpm_dir']
++ }
++ try:
++ module_name = name_map[uri.repo_type][0]
++ module_namespace = name_map[uri.repo_type][1]
++ repository = importlib.import_module(
++ 'kiwi.solver.repository.{0}'.format(module_namespace)
++ )
++ return repository.__dict__[module_name](
++ uri, user, secret
++ )
++ except Exception as issue:
+ raise KiwiSolverRepositorySetupError(
+- 'Support for %s solver repository type not implemented' %
+- uri.repo_type
++ 'Support for {0} solver repotype not implemented: {1}'.format(
++ uri.repo_type, issue
++ )
+ )
+diff --git a/kiwi/storage/subformat/__init__.py b/kiwi/storage/subformat/__init__.py
+index c36264bb4c..98e5dea357 100644
+--- a/kiwi/storage/subformat/__init__.py
++++ b/kiwi/storage/subformat/__init__.py
+@@ -15,25 +15,17 @@
+ # You should have received a copy of the GNU General Public License
+ # along with kiwi. If not, see
+ #
+-# project
+-from kiwi.storage.subformat.qcow2 import DiskFormatQcow2
+-from kiwi.storage.subformat.vhd import DiskFormatVhd
+-from kiwi.storage.subformat.vhdx import DiskFormatVhdx
+-from kiwi.storage.subformat.vhdfixed import DiskFormatVhdFixed
+-from kiwi.storage.subformat.vmdk import DiskFormatVmdk
+-from kiwi.storage.subformat.ova import DiskFormatOva
+-from kiwi.storage.subformat.gce import DiskFormatGce
+-from kiwi.storage.subformat.vdi import DiskFormatVdi
+-from kiwi.storage.subformat.base import DiskFormatBase
+-from kiwi.storage.subformat.vagrant_libvirt import DiskFormatVagrantLibVirt
+-from kiwi.storage.subformat.vagrant_virtualbox import DiskFormatVagrantVirtualBox
+-
+-from kiwi.exceptions import (
+- KiwiDiskFormatSetupError
++import importlib
++from abc import (
++ ABCMeta,
++ abstractmethod
+ )
+
++# project
++from kiwi.exceptions import KiwiDiskFormatSetupError
++
+
+-class DiskFormat:
++class DiskFormat(metaclass=ABCMeta):
+ """
+ **DiskFormat factory**
+
+@@ -42,42 +34,62 @@ class DiskFormat:
+ :param string root_dir: root directory path name
+ :param string target_dir: target directory path name
+ """
+- def __new__(self, name, xml_state, root_dir, target_dir): # noqa: C901
+- custom_args = xml_state.get_build_type_format_options()
+- if name == 'qcow2':
+- return DiskFormatQcow2(
+- xml_state, root_dir, target_dir, custom_args
++ @abstractmethod
++ def __init__(self) -> None:
++ return None # pragma: no cover
++
++ @abstractmethod
++ def new(
++ name: str, xml_state: object, root_dir: str, target_dir: str
++ ): # noqa: C901, E252
++ name_map = {
++ 'qcow2': 'Qcow2',
++ 'vdi': 'Vdi',
++ 'vhd': 'Vhd',
++ 'vhdx': 'Vhdx',
++ 'vhdfixed': 'VhdFixed',
++ 'gce': 'Gce',
++ 'vmdk': 'Vmdk',
++ 'ova': 'Ova',
++ 'vagrant_libvirt': 'VagrantLibVirt',
++ 'vagrant_virtualbox': 'VagrantVirtualBox',
++ 'base': 'Base'
++ }
++ try:
++ (custom_args, module_namespace) = DiskFormat._custom_args_for_format(
++ name, xml_state
+ )
+- elif name == 'vdi':
+- return DiskFormatVdi(
+- xml_state, root_dir, target_dir, custom_args
++ diskformat = importlib.import_module(
++ 'kiwi.storage.subformat.{0}'.format(module_namespace)
+ )
+- elif name == 'vhd':
+- return DiskFormatVhd(
++ module_name = 'DiskFormat{0}'.format(name_map[module_namespace])
++ return diskformat.__dict__[module_name](
+ xml_state, root_dir, target_dir, custom_args
+ )
+- elif name == 'vhdx':
+- return DiskFormatVhdx(
+- xml_state, root_dir, target_dir, custom_args
++ except Exception as issue:
++ raise KiwiDiskFormatSetupError(
++ 'No support for {0} disk format: {1}'.format(
++ module_namespace, issue
++ )
+ )
+- elif name == 'vhd-fixed':
++
++ @staticmethod
++ def _custom_args_for_format(name: str, xml_state: object):
++ custom_args = xml_state.get_build_type_format_options()
++ module_namespace = name
++ if name == 'vhd-fixed':
+ disk_tag = xml_state.build_type.get_vhdfixedtag()
+ if disk_tag:
+ custom_args.update(
+ {'--tag': disk_tag}
+ )
+- return DiskFormatVhdFixed(
+- xml_state, root_dir, target_dir, custom_args
+- )
++ module_namespace = 'vhdfixed'
+ elif name == 'gce':
+ gce_license_tag = xml_state.build_type.get_gcelicense()
+ if gce_license_tag:
+ custom_args.update(
+ {'--tag': gce_license_tag}
+ )
+- return DiskFormatGce(
+- xml_state, root_dir, target_dir, custom_args
+- )
+ elif name == 'vmdk' or name == 'ova':
+ vmdisk_section = xml_state.get_build_type_vmdisk_section()
+ if vmdisk_section:
+@@ -91,42 +103,15 @@ def __new__(self, name, xml_state, root_dir, target_dir): # noqa: C901
+ custom_args.update(
+ {'adapter_type={0}'.format(disk_controller): None}
+ )
+- if name == 'vmdk':
+- return DiskFormatVmdk(
+- xml_state, root_dir, target_dir, custom_args
+- )
+- else:
+- return DiskFormatOva(
+- xml_state, root_dir, target_dir, custom_args
+- )
+ elif name == 'vagrant':
+ vagrant_config = xml_state.get_build_type_vagrant_config_section()
+ if vagrant_config:
+ custom_args.update(
+ {'vagrantconfig': vagrant_config}
+ )
+- provider = vagrant_config.get_provider()
+- else:
+- provider = 'undefined'
+- if provider == 'libvirt':
+- return DiskFormatVagrantLibVirt(
+- xml_state, root_dir, target_dir, custom_args
+- )
+- elif provider == 'virtualbox':
+- return DiskFormatVagrantVirtualBox(
+- xml_state, root_dir, target_dir, custom_args
+- )
+- else:
+- raise KiwiDiskFormatSetupError(
+- 'No support for {0} format with {1} provider'.format(
+- name, provider
+- )
++ module_namespace = '{0}_{1}'.format(
++ name, vagrant_config.get_provider()
+ )
+ elif name == 'raw':
+- return DiskFormatBase(
+- xml_state, root_dir, target_dir, custom_args
+- )
+- else:
+- raise KiwiDiskFormatSetupError(
+- 'No support for {0} disk format'.format(name)
+- )
++ module_namespace = 'base'
++ return [custom_args, module_namespace]
+diff --git a/kiwi/tasks/image_info.py b/kiwi/tasks/image_info.py
+index c39009844e..37effead28 100644
+--- a/kiwi/tasks/image_info.py
++++ b/kiwi/tasks/image_info.py
+@@ -147,7 +147,7 @@ def _setup_solver(self):
+ repo_secret = xml_repo.get_password()
+ repo_type = xml_repo.get_type()
+ solver.add_repository(
+- SolverRepository(
++ SolverRepository.new(
+ Uri(repo_source, repo_type), repo_user, repo_secret
+ )
+ )
+diff --git a/kiwi/tasks/image_resize.py b/kiwi/tasks/image_resize.py
+index fcb1c5a792..bddb3b26a7 100644
+--- a/kiwi/tasks/image_resize.py
++++ b/kiwi/tasks/image_resize.py
+@@ -99,7 +99,7 @@ def process(self):
+
+ disk_format = self.xml_state.build_type.get_format()
+
+- image_format = DiskFormat(
++ image_format = DiskFormat.new(
+ disk_format or 'raw', self.xml_state, image_root,
+ abs_target_dir_path
+ )
+diff --git a/test/unit/builder/disk_test.py b/test/unit/builder/disk_test.py
+index 98db12b84d..9cb38dfa72 100644
+--- a/test/unit/builder/disk_test.py
++++ b/test/unit/builder/disk_test.py
+@@ -1,7 +1,6 @@
+-import mock
+ import sys
+ from mock import (
+- call, patch, mock_open
++ call, patch, mock_open, Mock, MagicMock
+ )
+ from pytest import raises
+ import kiwi
+@@ -43,13 +42,13 @@ def side_effect(filename):
+ '../data/example_disk_config.xml'
+ )
+ self.device_map = {
+- 'root': MappedDevice('/dev/root-device', mock.Mock()),
+- 'swap': MappedDevice('/dev/swap-device', mock.Mock()),
+- 'readonly': MappedDevice('/dev/readonly-root-device', mock.Mock()),
+- 'boot': MappedDevice('/dev/boot-device', mock.Mock()),
+- 'prep': MappedDevice('/dev/prep-device', mock.Mock()),
+- 'efi': MappedDevice('/dev/efi-device', mock.Mock()),
+- 'spare': MappedDevice('/dev/spare-device', mock.Mock())
++ 'root': MappedDevice('/dev/root-device', Mock()),
++ 'swap': MappedDevice('/dev/swap-device', Mock()),
++ 'readonly': MappedDevice('/dev/readonly-root-device', Mock()),
++ 'boot': MappedDevice('/dev/boot-device', Mock()),
++ 'prep': MappedDevice('/dev/prep-device', Mock()),
++ 'efi': MappedDevice('/dev/efi-device', Mock()),
++ 'spare': MappedDevice('/dev/spare-device', Mock())
+ }
+ self.id_map = {
+ 'kiwi_RootPart': 1,
+@@ -61,93 +60,86 @@ def side_effect(filename):
+ self.boot_names_type = namedtuple(
+ 'boot_names_type', ['kernel_name', 'initrd_name']
+ )
+- self.block_operation = mock.Mock()
+- self.block_operation.get_blkid = mock.Mock(
++ self.block_operation = Mock()
++ self.block_operation.get_blkid = Mock(
+ return_value='blkid_result'
+ )
+- self.block_operation.get_filesystem = mock.Mock(
++ self.block_operation.get_filesystem = Mock(
+ return_value='blkid_result_fs'
+ )
+- kiwi.builder.disk.BlockID = mock.Mock(
++ kiwi.builder.disk.BlockID = Mock(
+ return_value=self.block_operation
+ )
+- self.loop_provider = mock.Mock()
+- kiwi.builder.disk.LoopDevice = mock.Mock(
++ self.loop_provider = Mock()
++ kiwi.builder.disk.LoopDevice = Mock(
+ return_value=self.loop_provider
+ )
+- self.disk = mock.Mock()
+- provider = mock.Mock()
+- provider.get_device = mock.Mock(
++ self.disk = Mock()
++ provider = Mock()
++ provider.get_device = Mock(
+ return_value='/dev/some-loop'
+ )
+ self.disk.storage_provider = provider
+- self.partitioner = mock.Mock()
+- self.partitioner.get_id = mock.Mock(
++ self.partitioner = Mock()
++ self.partitioner.get_id = Mock(
+ return_value=1
+ )
+ self.disk.partitioner = self.partitioner
+- self.disk.get_uuid = mock.Mock(
++ self.disk.get_uuid = Mock(
+ return_value='0815'
+ )
+- self.disk.get_public_partition_id_map = mock.Mock(
++ self.disk.get_public_partition_id_map = Mock(
+ return_value=self.id_map_sorted
+ )
+- self.disk.get_device = mock.Mock(
++ self.disk.get_device = Mock(
+ return_value=self.device_map
+ )
+- kernel_info = mock.Mock()
++ kernel_info = Mock()
+ kernel_info.version = '1.2.3'
+ kernel_info.name = 'vmlinuz-1.2.3-default'
+- self.kernel = mock.Mock()
+- self.kernel.get_kernel = mock.Mock(
++ self.kernel = Mock()
++ self.kernel.get_kernel = Mock(
+ return_value=kernel_info
+ )
+- self.kernel.get_xen_hypervisor = mock.Mock()
+- self.kernel.copy_kernel = mock.Mock()
+- self.kernel.copy_xen_hypervisor = mock.Mock()
+- kiwi.builder.disk.Kernel = mock.Mock(
++ self.kernel.get_xen_hypervisor = Mock()
++ self.kernel.copy_kernel = Mock()
++ self.kernel.copy_xen_hypervisor = Mock()
++ kiwi.builder.disk.Kernel = Mock(
+ return_value=self.kernel
+ )
+- self.disk.subformat = mock.Mock()
+- self.disk.subformat.get_target_file_path_for_format = mock.Mock(
+- return_value='some-target-format-name'
+- )
+- kiwi.builder.disk.DiskFormat = mock.Mock(
+- return_value=self.disk.subformat
+- )
+- kiwi.builder.disk.Disk = mock.Mock(
++ kiwi.builder.disk.Disk = Mock(
+ return_value=self.disk
+ )
+- self.disk_setup = mock.Mock()
++ self.disk_setup = Mock()
+ self.disk_setup.get_disksize_mbytes.return_value = 1024
+ self.disk_setup.boot_partition_size.return_value = 0
+- self.disk_setup.get_efi_label = mock.Mock(
++ self.disk_setup.get_efi_label = Mock(
+ return_value='EFI'
+ )
+- self.disk_setup.get_root_label = mock.Mock(
++ self.disk_setup.get_root_label = Mock(
+ return_value='ROOT'
+ )
+- self.disk_setup.get_boot_label = mock.Mock(
++ self.disk_setup.get_boot_label = Mock(
+ return_value='BOOT'
+ )
+- self.disk_setup.need_boot_partition = mock.Mock(
++ self.disk_setup.need_boot_partition = Mock(
+ return_value=True
+ )
+- self.bootloader_install = mock.Mock()
+- kiwi.builder.disk.BootLoaderInstall.new = mock.MagicMock(
++ self.bootloader_install = Mock()
++ kiwi.builder.disk.BootLoaderInstall.new = MagicMock(
+ return_value=self.bootloader_install
+ )
+- self.bootloader_config = mock.Mock()
+- self.bootloader_config.get_boot_cmdline = mock.Mock(
++ self.bootloader_config = Mock()
++ self.bootloader_config.get_boot_cmdline = Mock(
+ return_value='boot_cmdline'
+ )
+- kiwi.builder.disk.BootLoaderConfig.new = mock.MagicMock(
++ kiwi.builder.disk.BootLoaderConfig.new = MagicMock(
+ return_value=self.bootloader_config
+ )
+- kiwi.builder.disk.DiskSetup = mock.MagicMock(
++ kiwi.builder.disk.DiskSetup = MagicMock(
+ return_value=self.disk_setup
+ )
+- self.boot_image_task = mock.Mock()
++ self.boot_image_task = Mock()
+ self.boot_image_task.boot_root_directory = 'boot_dir'
+ self.boot_image_task.kernel_filename = 'kernel'
+ self.boot_image_task.initrd_filename = 'initrd'
+@@ -156,40 +148,40 @@ def side_effect(filename):
+ kernel_name='linux.vmx',
+ initrd_name='initrd.vmx'
+ )
+- kiwi.builder.disk.BootImage.new = mock.Mock(
++ kiwi.builder.disk.BootImage.new = Mock(
+ return_value=self.boot_image_task
+ )
+- self.firmware = mock.Mock()
++ self.firmware = Mock()
+ self.firmware.get_legacy_bios_partition_size.return_value = 0
+ self.firmware.get_efi_partition_size.return_value = 0
+ self.firmware.get_prep_partition_size.return_value = 0
+- self.firmware.efi_mode = mock.Mock(
++ self.firmware.efi_mode = Mock(
+ return_value='efi'
+ )
+- kiwi.builder.disk.FirmWare = mock.Mock(
++ kiwi.builder.disk.FirmWare = Mock(
+ return_value=self.firmware
+ )
+- self.setup = mock.Mock()
+- kiwi.builder.disk.SystemSetup = mock.Mock(
++ self.setup = Mock()
++ kiwi.builder.disk.SystemSetup = Mock(
+ return_value=self.setup
+ )
+- self.install_image = mock.Mock()
+- kiwi.builder.disk.InstallImageBuilder = mock.Mock(
++ self.install_image = Mock()
++ kiwi.builder.disk.InstallImageBuilder = Mock(
+ return_value=self.install_image
+ )
+- self.raid_root = mock.Mock()
++ self.raid_root = Mock()
+ self.raid_root.get_device.return_value = MappedDevice(
+- '/dev/md0', mock.Mock()
++ '/dev/md0', Mock()
+ )
+- kiwi.builder.disk.RaidDevice = mock.Mock(
++ kiwi.builder.disk.RaidDevice = Mock(
+ return_value=self.raid_root
+ )
+- self.luks_root = mock.Mock()
+- kiwi.builder.disk.LuksDevice = mock.Mock(
++ self.luks_root = Mock()
++ kiwi.builder.disk.LuksDevice = Mock(
+ return_value=self.luks_root
+ )
+- self.fstab = mock.Mock()
+- kiwi.builder.disk.Fstab = mock.Mock(
++ self.fstab = Mock()
++ kiwi.builder.disk.Fstab = Mock(
+ return_value=self.fstab
+ )
+ self.disk_builder = DiskBuilder(
+@@ -236,7 +228,7 @@ def test_create_disk_overlay_with_volume_setup_not_supported(self):
+ def test_create_install_media(
+ self, mock_wipe, mock_load, mock_path
+ ):
+- result_instance = mock.Mock()
++ result_instance = Mock()
+ mock_path.return_value = True
+ self.disk_builder.install_iso = True
+ self.disk_builder.install_pxe = True
+@@ -248,7 +240,7 @@ def test_create_install_media(
+
+ @patch('os.path.exists')
+ def test_create_install_media_no_boot_instance_found(self, mock_path):
+- result_instance = mock.Mock()
++ result_instance = Mock()
+ mock_path.return_value = False
+ self.disk_builder.install_iso = True
+ with raises(KiwiInstallMediaError):
+@@ -257,7 +249,7 @@ def test_create_install_media_no_boot_instance_found(self, mock_path):
+ @patch('os.path.exists')
+ @patch('pickle.load')
+ def test_create_install_media_pickle_load_error(self, mock_load, mock_path):
+- result_instance = mock.Mock()
++ result_instance = Mock()
+ mock_load.side_effect = Exception
+ mock_path.return_value = True
+ self.disk_builder.install_iso = True
+@@ -274,7 +266,7 @@ def test_create_disk_standard_root_with_kiwi_initrd(
+ ):
+ mock_path.return_value = True
+ mock_rand.return_value = 15
+- filesystem = mock.Mock()
++ filesystem = Mock()
+ mock_fs.return_value = filesystem
+ self.disk_builder.volume_manager_name = None
+ self.disk_builder.initrd_system = 'kiwi'
+@@ -406,12 +398,12 @@ def test_create_disk_standard_root_with_dracut_initrd(
+ )
+ mock_path.return_value = True
+ mock_rand.return_value = 15
+- filesystem = mock.Mock()
++ filesystem = Mock()
+ mock_fs.return_value = filesystem
+ self.disk_builder.volume_manager_name = None
+ self.disk_builder.initrd_system = 'dracut'
+ self.setup.script_exists.return_value = True
+- disk_system = mock.Mock()
++ disk_system = Mock()
+ mock_SystemSetup.return_value = disk_system
+
+ m_open = mock_open()
+@@ -543,10 +535,10 @@ def test_create_disk_standard_root_is_overlay(
+ mock_rand.return_value = 15
+ self.disk_builder.root_filesystem_is_overlay = True
+ self.disk_builder.volume_manager_name = None
+- squashfs = mock.Mock()
++ squashfs = Mock()
+ mock_squashfs.return_value = squashfs
+ mock_getsize.return_value = 1048576
+- tempfile = mock.Mock()
++ tempfile = Mock()
+ tempfile.name = 'tempname'
+ mock_temp.return_value = tempfile
+ mock_exists.return_value = True
+@@ -609,11 +601,11 @@ def test_create_disk_standard_root_no_hypervisor_found(
+ def test_create_disk_standard_root_xen_server_boot(
+ self, mock_command, mock_fs
+ ):
+- filesystem = mock.Mock()
++ filesystem = Mock()
+ mock_fs.return_value = filesystem
+ self.disk_builder.volume_manager_name = None
+ self.disk_builder.xen_server = True
+- self.firmware.efi_mode = mock.Mock(
++ self.firmware.efi_mode = Mock(
+ return_value=False
+ )
+
+@@ -631,10 +623,10 @@ def test_create_disk_standard_root_s390_boot(
+ self, mock_grub_dir, mock_command, mock_fs
+ ):
+ self.disk_builder.arch = 's390x'
+- filesystem = mock.Mock()
++ filesystem = Mock()
+ mock_fs.return_value = filesystem
+ self.disk_builder.volume_manager_name = None
+- self.firmware.efi_mode = mock.Mock(
++ self.firmware.efi_mode = Mock(
+ return_value=False
+ )
+ self.disk_builder.bootloader = 'grub2_s390x_emu'
+@@ -650,10 +642,10 @@ def test_create_disk_standard_root_s390_boot(
+ def test_create_disk_standard_root_secure_boot(
+ self, mock_grub_dir, mock_command, mock_fs
+ ):
+- filesystem = mock.Mock()
++ filesystem = Mock()
+ mock_fs.return_value = filesystem
+ self.disk_builder.volume_manager_name = None
+- self.firmware.efi_mode = mock.Mock(
++ self.firmware.efi_mode = Mock(
+ return_value='uefi'
+ )
+ with patch('builtins.open'):
+@@ -668,7 +660,7 @@ def test_create_disk_standard_root_secure_boot(
+ def test_create_disk_mdraid_root(
+ self, mock_grub_dir, mock_command, mock_fs
+ ):
+- filesystem = mock.Mock()
++ filesystem = Mock()
+ mock_fs.return_value = filesystem
+ self.disk_builder.volume_manager_name = None
+ self.disk_builder.mdraid = 'mirroring'
+@@ -697,7 +689,7 @@ def test_create_disk_mdraid_root(
+ def test_create_disk_luks_root(
+ self, mock_grub_dir, mock_command, mock_fs
+ ):
+- filesystem = mock.Mock()
++ filesystem = Mock()
+ mock_fs.return_value = filesystem
+ self.disk_builder.volume_manager_name = None
+ self.disk_builder.luks = 'passphrase'
+@@ -733,18 +725,18 @@ def test_create_disk_volume_managed_root(
+ mock_volume_manager, mock_fs
+ ):
+ mock_exists.return_value = True
+- volume_manager = mock.Mock()
+- volume_manager.get_device = mock.Mock(
++ volume_manager = Mock()
++ volume_manager.get_device = Mock(
+ return_value={
+- 'root': MappedDevice('/dev/systemVG/LVRoot', mock.Mock()),
+- 'swap': MappedDevice('/dev/systemVG/LVSwap', mock.Mock())
++ 'root': MappedDevice('/dev/systemVG/LVRoot', Mock()),
++ 'swap': MappedDevice('/dev/systemVG/LVSwap', Mock())
+ }
+ )
+- volume_manager.get_fstab = mock.Mock(
++ volume_manager.get_fstab = Mock(
+ return_value=['fstab_volume_entries']
+ )
+ mock_volume_manager.return_value = volume_manager
+- filesystem = mock.Mock()
++ filesystem = Mock()
+ mock_fs.return_value = filesystem
+ self.disk_builder.volume_manager_name = 'lvm'
+
+@@ -780,7 +772,7 @@ def test_create_disk_volume_managed_root(
+ def test_create_disk_hybrid_gpt_requested(
+ self, mock_grub_dir, mock_command, mock_fs
+ ):
+- filesystem = mock.Mock()
++ filesystem = Mock()
+ mock_fs.return_value = filesystem
+ self.disk_builder.volume_manager_name = None
+ self.disk_builder.install_media = False
+@@ -797,7 +789,7 @@ def test_create_disk_hybrid_gpt_requested(
+ def test_create_disk_force_mbr_requested(
+ self, mock_grub_dir, mock_command, mock_fs
+ ):
+- filesystem = mock.Mock()
++ filesystem = Mock()
+ mock_fs.return_value = filesystem
+ self.disk_builder.volume_manager_name = None
+ self.disk_builder.install_media = False
+@@ -812,8 +804,8 @@ def test_create_disk_force_mbr_requested(
+ def test_create(
+ self, mock_builder
+ ):
+- result = mock.Mock()
+- builder = mock.Mock()
++ result = Mock()
++ builder = Mock()
+ builder.create_disk.return_value = result
+ builder.create_install_media.return_value = result
+ mock_builder.return_value = builder
+@@ -831,7 +823,7 @@ def test_create(
+ def test_create_disk_spare_part_requested(
+ self, mock_grub_dir, mock_command, mock_fs
+ ):
+- filesystem = mock.Mock()
++ filesystem = Mock()
+ mock_fs.return_value = filesystem
+ self.disk_builder.volume_manager_name = None
+ self.disk_builder.install_media = False
+@@ -879,15 +871,15 @@ def test_create_disk_spare_part_requested(
+
+ @patch('kiwi.builder.disk.LoopDevice')
+ @patch('kiwi.builder.disk.Partitioner')
+- @patch('kiwi.builder.disk.DiskFormat')
++ @patch('kiwi.builder.disk.DiskFormat.new')
+ def test_append_unpartitioned_space(
+ self, mock_diskformat, mock_partitioner, mock_loopdevice
+ ):
+- loopdevice = mock.Mock()
++ loopdevice = Mock()
+ mock_loopdevice.return_value = loopdevice
+- partitioner = mock.Mock()
++ partitioner = Mock()
+ mock_partitioner.return_value = partitioner
+- disk_format = mock.Mock()
++ disk_format = Mock()
+ mock_diskformat.return_value = disk_format
+ self.disk_builder.unpartitioned_bytes = 1024
+ self.disk_builder.append_unpartitioned_space()
+@@ -899,9 +891,12 @@ def test_append_unpartitioned_space(
+
+ @patch('kiwi.builder.disk.FileSystem.new')
+ @patch('kiwi.builder.disk.Command.run')
+- def test_create_disk_format(self, mock_command, mock_fs):
+- result_instance = mock.Mock()
+- filesystem = mock.Mock()
++ @patch('kiwi.builder.disk.DiskFormat.new')
++ def test_create_disk_format(self, mock_DiskFormat, mock_command, mock_fs):
++ disk_subformat = Mock()
++ mock_DiskFormat.return_value = disk_subformat
++ result_instance = Mock()
++ filesystem = Mock()
+ mock_fs.return_value = filesystem
+ self.disk_builder.install_media = False
+ self.disk_builder.image_format = 'vmdk'
+@@ -909,4 +904,4 @@ def test_create_disk_format(self, mock_command, mock_fs):
+ with patch('builtins.open'):
+ self.disk_builder.create_disk_format(result_instance)
+
+- self.disk.subformat.create_image_format.assert_called_once_with()
++ disk_subformat.create_image_format.assert_called_once_with()
+diff --git a/test/unit/solver/repository/init_test.py b/test/unit/solver/repository/init_test.py
+index 8c0f95a376..67a96bddd1 100644
+--- a/test/unit/solver/repository/init_test.py
++++ b/test/unit/solver/repository/init_test.py
+@@ -15,22 +15,22 @@ def setup(self):
+
+ def test_solver_repository_type_not_implemented(self):
+ with raises(KiwiSolverRepositorySetupError):
+- SolverRepository(self.uri)
++ SolverRepository.new(self.uri)
+
+- @patch('kiwi.solver.repository.SolverRepositorySUSE')
++ @patch('kiwi.solver.repository.suse.SolverRepositorySUSE')
+ def test_solver_repository_suse(self, mock_suse):
+ self.uri.repo_type = 'yast2'
+- SolverRepository(self.uri)
++ SolverRepository.new(self.uri)
+ mock_suse.assert_called_once_with(self.uri, None, None)
+
+- @patch('kiwi.solver.repository.SolverRepositoryRpmMd')
++ @patch('kiwi.solver.repository.rpm_md.SolverRepositoryRpmMd')
+ def test_solver_repository_rpm_md(self, mock_rpm_md):
+ self.uri.repo_type = 'rpm-md'
+- SolverRepository(self.uri)
++ SolverRepository.new(self.uri)
+ mock_rpm_md.assert_called_once_with(self.uri, None, None)
+
+- @patch('kiwi.solver.repository.SolverRepositoryRpmDir')
++ @patch('kiwi.solver.repository.rpm_dir.SolverRepositoryRpmDir')
+ def test_solver_repository_rpm_dir(self, mock_rpm_dir):
+ self.uri.repo_type = 'rpm-dir'
+- SolverRepository(self.uri)
++ SolverRepository.new(self.uri)
+ mock_rpm_dir.assert_called_once_with(self.uri, None, None)
+diff --git a/test/unit/storage/subformat/init_test.py b/test/unit/storage/subformat/init_test.py
+index f55343122f..0bb2fa2e86 100644
+--- a/test/unit/storage/subformat/init_test.py
++++ b/test/unit/storage/subformat/init_test.py
+@@ -15,67 +15,67 @@ def setup(self):
+
+ def test_format_not_implemented(self):
+ with raises(KiwiDiskFormatSetupError):
+- DiskFormat('foo', self.xml_state, 'root_dir', 'target_dir')
++ DiskFormat.new('foo', self.xml_state, 'root_dir', 'target_dir')
+
+ def test_disk_format_vagrant_not_implemented(self):
+ self.xml_state.get_build_type_vagrant_config_section = Mock(
+ return_value=None
+ )
+ with raises(KiwiDiskFormatSetupError):
+- DiskFormat(
++ DiskFormat.new(
+ 'vagrant', self.xml_state, 'root_dir', 'target_dir'
+ )
+
+- @patch('kiwi.storage.subformat.DiskFormatQcow2')
++ @patch('kiwi.storage.subformat.qcow2.DiskFormatQcow2')
+ def test_disk_format_qcow2(self, mock_qcow2):
+- DiskFormat('qcow2', self.xml_state, 'root_dir', 'target_dir')
++ DiskFormat.new('qcow2', self.xml_state, 'root_dir', 'target_dir')
+ mock_qcow2.assert_called_once_with(
+ self.xml_state, 'root_dir', 'target_dir', {}
+ )
+
+- @patch('kiwi.storage.subformat.DiskFormatVdi')
++ @patch('kiwi.storage.subformat.vdi.DiskFormatVdi')
+ def test_disk_format_vdi(self, mock_vdi):
+- DiskFormat('vdi', self.xml_state, 'root_dir', 'target_dir')
++ DiskFormat.new('vdi', self.xml_state, 'root_dir', 'target_dir')
+ mock_vdi.assert_called_once_with(
+ self.xml_state, 'root_dir', 'target_dir', {}
+ )
+
+- @patch('kiwi.storage.subformat.DiskFormatVhd')
++ @patch('kiwi.storage.subformat.vhd.DiskFormatVhd')
+ def test_disk_format_vhd(self, mock_vhd):
+- DiskFormat('vhd', self.xml_state, 'root_dir', 'target_dir')
++ DiskFormat.new('vhd', self.xml_state, 'root_dir', 'target_dir')
+ mock_vhd.assert_called_once_with(
+ self.xml_state, 'root_dir', 'target_dir', {}
+ )
+
+- @patch('kiwi.storage.subformat.DiskFormatVhdx')
++ @patch('kiwi.storage.subformat.vhdx.DiskFormatVhdx')
+ def test_disk_format_vhdx(self, mock_vhdx):
+- DiskFormat('vhdx', self.xml_state, 'root_dir', 'target_dir')
++ DiskFormat.new('vhdx', self.xml_state, 'root_dir', 'target_dir')
+ mock_vhdx.assert_called_once_with(
+ self.xml_state, 'root_dir', 'target_dir', {}
+ )
+
+- @patch('kiwi.storage.subformat.DiskFormatVhdFixed')
++ @patch('kiwi.storage.subformat.vhdfixed.DiskFormatVhdFixed')
+ def test_disk_format_vhdfixed(self, mock_vhdfixed):
+ self.xml_state.build_type.get_vhdfixedtag = Mock(
+ return_value='disk-tag'
+ )
+- DiskFormat('vhd-fixed', self.xml_state, 'root_dir', 'target_dir')
++ DiskFormat.new('vhd-fixed', self.xml_state, 'root_dir', 'target_dir')
+ mock_vhdfixed.assert_called_once_with(
+ self.xml_state, 'root_dir', 'target_dir', {'--tag': 'disk-tag'}
+ )
+
+- @patch('kiwi.storage.subformat.DiskFormatGce')
++ @patch('kiwi.storage.subformat.gce.DiskFormatGce')
+ def test_disk_format_gce(self, mock_gce):
+ self.xml_state.build_type.get_gcelicense = Mock(
+ return_value='gce_license_tag'
+ )
+- DiskFormat('gce', self.xml_state, 'root_dir', 'target_dir')
++ DiskFormat.new('gce', self.xml_state, 'root_dir', 'target_dir')
+ mock_gce.assert_called_once_with(
+ self.xml_state, 'root_dir', 'target_dir',
+ {'--tag': 'gce_license_tag'}
+ )
+
+- @patch('kiwi.storage.subformat.DiskFormatVmdk')
++ @patch('kiwi.storage.subformat.vmdk.DiskFormatVmdk')
+ def test_disk_format_vmdk(self, mock_vmdk):
+ vmdisk = Mock()
+ vmdisk.get_controller = Mock(
+@@ -87,13 +87,13 @@ def test_disk_format_vmdk(self, mock_vmdk):
+ self.xml_state.get_build_type_vmdisk_section = Mock(
+ return_value=vmdisk
+ )
+- DiskFormat('vmdk', self.xml_state, 'root_dir', 'target_dir')
++ DiskFormat.new('vmdk', self.xml_state, 'root_dir', 'target_dir')
+ mock_vmdk.assert_called_once_with(
+ self.xml_state, 'root_dir', 'target_dir',
+ {'adapter_type=controller': None, 'subformat=disk-mode': None}
+ )
+
+- @patch('kiwi.storage.subformat.DiskFormatOva')
++ @patch('kiwi.storage.subformat.ova.DiskFormatOva')
+ def test_disk_format_ova(self, mock_ova):
+ vmdisk = Mock()
+ vmdisk.get_controller = Mock(
+@@ -105,14 +105,14 @@ def test_disk_format_ova(self, mock_ova):
+ self.xml_state.get_build_type_vmdisk_section = Mock(
+ return_value=vmdisk
+ )
+- DiskFormat('ova', self.xml_state, 'root_dir', 'target_dir')
++ DiskFormat.new('ova', self.xml_state, 'root_dir', 'target_dir')
+ mock_ova.assert_called_once_with(
+ self.xml_state, 'root_dir', 'target_dir',
+ {'adapter_type=controller': None, 'subformat=disk-mode': None}
+ )
+
+- @patch('kiwi.storage.subformat.DiskFormatVagrantVirtualBox')
+- @patch('kiwi.storage.subformat.DiskFormatVagrantLibVirt')
++ @patch('kiwi.storage.subformat.vagrant_virtualbox.DiskFormatVagrantVirtualBox')
++ @patch('kiwi.storage.subformat.vagrant_libvirt.DiskFormatVagrantLibVirt')
+ def test_disk_format_vagrant_libvirt(
+ self, mock_vagrant_libvirt, mock_vagrant_virt_box
+ ):
+@@ -127,7 +127,7 @@ def test_disk_format_vagrant_libvirt(
+ self.xml_state.get_build_type_vagrant_config_section = Mock(
+ return_value=vagrant_config
+ )
+- DiskFormat(
++ DiskFormat.new(
+ 'vagrant', self.xml_state, 'root_dir', 'target_dir'
+ )
+ provider_mock.assert_called_once_with(
+@@ -135,9 +135,9 @@ def test_disk_format_vagrant_libvirt(
+ {'vagrantconfig': vagrant_config}
+ )
+
+- @patch('kiwi.storage.subformat.DiskFormatBase')
++ @patch('kiwi.storage.subformat.base.DiskFormatBase')
+ def test_disk_format_base(self, mock_base):
+- DiskFormat('raw', self.xml_state, 'root_dir', 'target_dir')
++ DiskFormat.new('raw', self.xml_state, 'root_dir', 'target_dir')
+ mock_base.assert_called_once_with(
+ self.xml_state, 'root_dir', 'target_dir', {}
+ )
+diff --git a/test/unit/tasks/image_resize_test.py b/test/unit/tasks/image_resize_test.py
+index 81248b6e2d..4f6b14c1a1 100644
+--- a/test/unit/tasks/image_resize_test.py
++++ b/test/unit/tasks/image_resize_test.py
+@@ -1,7 +1,9 @@
+ import logging
+ import os
+ import sys
+-from mock import Mock
++from mock import (
++ Mock, patch
++)
+ from pytest import (
+ raises, fixture
+ )
+@@ -41,12 +43,6 @@ def setup(self):
+ )
+ self.partitioner = Mock()
+ self.loop_provider = Mock()
+- self.image_format = Mock()
+- self.image_format.has_raw_disk = Mock()
+- self.image_format.diskname = 'some-disk.raw'
+- kiwi.tasks.image_resize.DiskFormat = Mock(
+- return_value=self.image_format
+- )
+ kiwi.tasks.image_resize.FirmWare = Mock(
+ return_value=self.firmware
+ )
+@@ -75,69 +71,87 @@ def test_process_no_root_directory_specified(self):
+ with raises(KiwiConfigFileNotFound):
+ self.task.process()
+
+- def test_process_no_raw_disk_found(self):
++ @patch('kiwi.tasks.image_resize.DiskFormat.new')
++ def test_process_no_raw_disk_found(self, mock_DiskFormat):
++ image_format = Mock()
++ image_format.has_raw_disk.return_value = False
++ mock_DiskFormat.return_value = image_format
+ self._init_command_args()
+- self.image_format.has_raw_disk.return_value = False
+ self.task.command_args['resize'] = True
+ with raises(KiwiImageResizeError):
+ self.task.process()
+
+- def test_process_unsupported_size_format(self):
++ @patch('kiwi.tasks.image_resize.DiskFormat.new')
++ def test_process_unsupported_size_format(self, mock_DiskFormat):
++ image_format = Mock()
++ image_format.has_raw_disk.return_value = True
++ mock_DiskFormat.return_value = image_format
+ self._init_command_args()
+ self.task.command_args['--size'] = '20x'
+- self.image_format.has_raw_disk.return_value = True
+ self.task.command_args['resize'] = True
+ with raises(KiwiSizeError):
+ self.task.process()
+
+- def test_process_image_resize_gb(self):
++ @patch('kiwi.tasks.image_resize.DiskFormat.new')
++ def test_process_image_resize_gb(self, mock_DiskFormat):
++ image_format = Mock()
++ image_format.resize_raw_disk.return_value = True
++ mock_DiskFormat.return_value = image_format
+ self._init_command_args()
+ self.task.command_args['resize'] = True
+- self.image_format.resize_raw_disk.return_value = True
+ self.task.process()
+ self.loop_provider.create.assert_called_once_with(overwrite=False)
+ self.partitioner.resize_table.assert_called_once_with()
+- self.image_format.resize_raw_disk.assert_called_once_with(
++ image_format.resize_raw_disk.assert_called_once_with(
+ 42 * 1024 * 1024 * 1024
+ )
+- self.image_format.create_image_format.assert_called_once_with()
++ image_format.create_image_format.assert_called_once_with()
+
+- def test_process_image_resize_mb(self):
++ @patch('kiwi.tasks.image_resize.DiskFormat.new')
++ def test_process_image_resize_mb(self, mock_DiskFormat):
++ image_format = Mock()
++ image_format.resize_raw_disk.return_value = True
++ mock_DiskFormat.return_value = image_format
+ self._init_command_args()
+ self.task.command_args['resize'] = True
+ self.task.command_args['--size'] = '42m'
+- self.image_format.resize_raw_disk.return_value = True
+ self.task.process()
+ self.loop_provider.create.assert_called_once_with(overwrite=False)
+ self.partitioner.resize_table.assert_called_once_with()
+- self.image_format.resize_raw_disk.assert_called_once_with(
++ image_format.resize_raw_disk.assert_called_once_with(
+ 42 * 1024 * 1024
+ )
+- self.image_format.create_image_format.assert_called_once_with()
++ image_format.create_image_format.assert_called_once_with()
+
+- def test_process_image_resize_bytes(self):
++ @patch('kiwi.tasks.image_resize.DiskFormat.new')
++ def test_process_image_resize_bytes(self, mock_DiskFormat):
++ image_format = Mock()
++ image_format.resize_raw_disk.return_value = True
++ mock_DiskFormat.return_value = image_format
+ self._init_command_args()
+ self.task.command_args['resize'] = True
+ self.task.command_args['--size'] = '42'
+- self.image_format.resize_raw_disk.return_value = True
+ self.task.process()
+ self.loop_provider.create.assert_called_once_with(overwrite=False)
+ self.partitioner.resize_table.assert_called_once_with()
+- self.image_format.resize_raw_disk.assert_called_once_with(
++ image_format.resize_raw_disk.assert_called_once_with(
+ 42
+ )
+- self.image_format.create_image_format.assert_called_once_with()
++ image_format.create_image_format.assert_called_once_with()
+
+- def test_process_image_resize_not_needed(self):
++ @patch('kiwi.tasks.image_resize.DiskFormat.new')
++ def test_process_image_resize_not_needed(self, mock_DiskFormat):
++ image_format = Mock()
++ image_format.resize_raw_disk.return_value = False
++ mock_DiskFormat.return_value = image_format
+ self._init_command_args()
+ self.task.command_args['resize'] = True
+ self.task.command_args['--size'] = '42'
+- self.image_format.resize_raw_disk.return_value = False
+ with self._caplog.at_level(logging.INFO):
+ self.task.process()
+ self.loop_provider.create.assert_called_once_with(overwrite=False)
+ self.partitioner.resize_table.assert_called_once_with()
+- self.image_format.resize_raw_disk.assert_called_once_with(
++ image_format.resize_raw_disk.assert_called_once_with(
+ 42
+ )
+ assert 'Loading XML description' in self._caplog.text
diff --git a/kiwi.spec b/kiwi.spec
index e59772ea8362d71e3616a30ce27bb204a27f4290..abddd7423b581b4e031d717c458a831becdea340 100644
--- a/kiwi.spec
+++ b/kiwi.spec
@@ -2,12 +2,14 @@
Name: kiwi
Version: 9.21.5
-Release: 1
+Release: 2
License: GPLv3+
Summary: Flexible operating system image builder
URL: http://osinside.github.io/kiwi/
Source0: https://files.pythonhosted.org/packages/source/k/%{name}/%{name}-%{version}.tar.gz
+Patch6000: 223abea7c4c1fd2871956c61de607682d2409a1e.patch
+Patch6001: 36003143223010c629755b3a24e616f7c66b1f5f.patch
BuildRequires: bash-completion dracut fdupes gcc make
BuildRequires: python3-devel python3-setuptools shadow-utils
@@ -189,6 +191,9 @@ done
%{_mandir}/man8/%{name}*
%changelog
+* 20201102233007659303 patch-tracking 9.21.5-2
+- append patch file of upstream repository from <223abea7c4c1fd2871956c61de607682d2409a1e> to <36003143223010c629755b3a24e616f7c66b1f5f>
+
* Tue Jul 28 2020 xinghe - 9.21.5-1
- update version to 9.21.5
@@ -208,4 +213,4 @@ done
- Remove python2 dependency
* Sat Sep 21 2019 openEuler Buildteam - 9.16.12-2
-- Package init
+- Package init
\ No newline at end of file