From 773db92b4dcdeef417cdf5a54ec0aa823bc043cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= Date: Thu, 14 Jan 2016 13:59:11 +0100 Subject: [PATCH] Added FileSystemClicFs class --- kiwi/filesystem.py | 5 ++ kiwi/filesystem_clicfs.py | 71 +++++++++++++++++++++++++++++ test/unit/filesystem_clicfs_test.py | 66 +++++++++++++++++++++++++++ test/unit/filesystem_test.py | 6 +++ 4 files changed, 148 insertions(+) create mode 100644 kiwi/filesystem_clicfs.py create mode 100644 test/unit/filesystem_clicfs_test.py diff --git a/kiwi/filesystem.py b/kiwi/filesystem.py index dd016b0b..b7e7ac06 100644 --- a/kiwi/filesystem.py +++ b/kiwi/filesystem.py @@ -24,6 +24,7 @@ from filesystem_xfs import FileSystemXfs from filesystem_fat16 import FileSystemFat16 from filesystem_fat32 import FileSystemFat32 from filesystem_squashfs import FileSystemSquashFs +from filesystem_clicfs import FileSystemClicFs from exceptions import ( KiwiFileSystemSetupError @@ -67,6 +68,10 @@ class FileSystem(object): return FileSystemSquashFs( device_provider, source_dir, custom_args ) + elif name == 'clicfs': + return FileSystemClicFs( + device_provider, source_dir, custom_args + ) else: raise KiwiFileSystemSetupError( 'Support for %s filesystem not implemented' % name diff --git a/kiwi/filesystem_clicfs.py b/kiwi/filesystem_clicfs.py new file mode 100644 index 00000000..f87d6d13 --- /dev/null +++ b/kiwi/filesystem_clicfs.py @@ -0,0 +1,71 @@ +# Copyright (c) 2015 SUSE Linux GmbH. All rights reserved. +# +# This file is part of kiwi. +# +# kiwi is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# kiwi is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kiwi. If not, see +# +# project +from command import Command +from filesystem_base import FileSystemBase +from filesystem_ext4 import FileSystemExt4 +from system_size import SystemSize +from tempfile import mkdtemp +from path import Path +from loop_device import LoopDevice +from logger import log + + +class FileSystemClicFs(FileSystemBase): + """ + Implements creation of clicfs filesystem + """ + def post_init(self, custom_args): + self.container_dir = None + self.custom_args = custom_args + + def create_on_file(self, filename, label=None): + # there is no label which could be set for clicfs + # thus this parameter is not used + self.container_dir = mkdtemp() + clicfs_container_filesystem = self.container_dir + '/fsdata.ext4' + loop_provider = LoopDevice( + clicfs_container_filesystem, + self.__get_container_filesystem_size_mbytes() + ) + filesystem = FileSystemExt4( + loop_provider, self.source_dir + ) + filesystem.create_on_device() + Command.run( + ['resize2fs', loop_provider.get_device(), '-M'] + ) + filesystem.sync_data() + + # force cleanup and umount of container filesystem + # before mkclicfs is called + del filesystem + + Command.run( + ['mkclicfs', clicfs_container_filesystem, filename] + ) + + def __get_container_filesystem_size_mbytes(self): + size = SystemSize(self.source_dir) + source_dir_mbytes = size.accumulate_mbyte_file_sizes() + return size.customize(source_dir_mbytes, 'ext4') + + def __del__(self): + if self.container_dir: + log.info('Cleaning up %s instance', type(self).__name__) + Path.wipe(self.container_dir) diff --git a/test/unit/filesystem_clicfs_test.py b/test/unit/filesystem_clicfs_test.py new file mode 100644 index 00000000..3a9ba2f2 --- /dev/null +++ b/test/unit/filesystem_clicfs_test.py @@ -0,0 +1,66 @@ +from nose.tools import * +from mock import patch +from mock import call +import mock + +import nose_helper + +from kiwi.exceptions import * +from kiwi.filesystem_clicfs import FileSystemClicFs + + +class TestFileSystemClicFs(object): + @patch('os.path.exists') + def setup(self, mock_exists): + mock_exists.return_value = True + self.clicfs = FileSystemClicFs(mock.Mock(), 'source_dir') + + @patch('kiwi.filesystem_clicfs.Command.run') + @patch('kiwi.filesystem_clicfs.mkdtemp') + @patch('kiwi.filesystem_clicfs.LoopDevice') + @patch('kiwi.filesystem_clicfs.FileSystemExt4') + @patch('kiwi.filesystem_clicfs.SystemSize') + @patch('kiwi.filesystem_clicfs.Path.wipe') + def test_create_on_file( + self, mock_wipe, mock_size, mock_ext4, mock_loop, + mock_dtemp, mock_command + ): + size = mock.Mock() + size.customize = mock.Mock( + return_value=42 + ) + size.accumulate_mbyte_file_sizes = mock.Mock( + return_value=42 + ) + mock_size.return_value = size + filesystem = mock.Mock() + mock_ext4.return_value = filesystem + loop_provider = mock.Mock() + mock_loop.return_value = loop_provider + mock_dtemp.return_value = 'tmpdir' + + self.clicfs.create_on_file('myimage', 'label') + + size.accumulate_mbyte_file_sizes.assert_called_once_with() + size.customize.assert_called_once_with(42, 'ext4') + mock_loop.assert_called_once_with( + 'tmpdir/fsdata.ext4', 42 + ) + mock_ext4.assert_called_once_with( + loop_provider, 'source_dir' + ) + filesystem.create_on_device.assert_called_once_with() + assert mock_command.call_args_list == [ + call( + ['resize2fs', loop_provider.get_device(), '-M'] + ), + call( + ['mkclicfs', 'tmpdir/fsdata.ext4', 'myimage'] + ) + ] + + @patch('kiwi.filesystem_clicfs.Path.wipe') + def test_destructor(self, mock_wipe): + self.clicfs.container_dir = 'tmpdir' + self.clicfs.__del__() + mock_wipe.assert_called_once_with('tmpdir') diff --git a/test/unit/filesystem_test.py b/test/unit/filesystem_test.py index 5d2d0234..5b93d2a7 100644 --- a/test/unit/filesystem_test.py +++ b/test/unit/filesystem_test.py @@ -61,3 +61,9 @@ class TestFileSystem(object): provider = mock.Mock() FileSystem('squashfs', provider, 'source_dir') mock_squashfs.assert_called_once_with(provider, 'source_dir', None) + + @patch('kiwi.filesystem.FileSystemClicFs') + def test_filesystem_clicfs(self, mock_clicfs): + provider = mock.Mock() + FileSystem('clicfs', provider, 'source_dir') + mock_clicfs.assert_called_once_with(provider, 'source_dir', None)