class TestCompress(object): @patch('os.path.exists') def setup(self, mock_exists): mock_exists.return_value = True self.compress = Compress('some-file', True) @raises(KiwiFileNotFound) def test_source_file_not_found(self): Compress('some-file') @patch('kiwi.command.Command.run') def test_xz(self, mock_command): self.compress.xz() mock_command.assert_called_once_with([ 'xz', '-f', '--check=crc32', '--lzma2=dict=512KiB', '--keep', 'some-file' ]) assert self.compress.compressed_filename == 'some-file.xz' @patch('kiwi.command.Command.run') def test_gzip(self, mock_command): self.compress.gzip() mock_command.assert_called_once_with( ['gzip', '-f', '-9', '--keep', 'some-file']) assert self.compress.compressed_filename == 'some-file.gz' @patch('kiwi.command.Command.run') @patch('kiwi.utils.compress.NamedTemporaryFile') @patch('kiwi.utils.compress.Compress.get_format') def test_uncompress(self, mock_format, mock_temp, mock_command): mock_format.return_value = 'xz' self.compress.uncompress() mock_command.assert_called_once_with(['xz', '-d', 'some-file']) assert self.compress.uncompressed_filename == 'some-file' @patch('kiwi.command.Command.run') @patch('kiwi.utils.compress.NamedTemporaryFile') @patch('kiwi.utils.compress.Compress.get_format') def test_uncompress_temporary(self, mock_format, mock_temp, mock_command): tempfile = mock.Mock() tempfile.name = 'tempfile' mock_temp.return_value = tempfile mock_format.return_value = 'xz' self.compress.uncompress(temporary=True) mock_command.assert_called_once_with( ['bash', '-c', 'xz -c -d some-file > tempfile']) assert self.compress.uncompressed_filename == 'tempfile' @raises(KiwiCompressionFormatUnknown) @patch('kiwi.utils.compress.Compress.get_format') def test_uncompress_unknown_format(self, mock_format): mock_format.return_value = None self.compress.uncompress() def test_get_format(self): xz = Compress('../data/xz_data.xz') assert xz.get_format() == 'xz' gzip = Compress('../data/gz_data.gz') assert gzip.get_format() == 'gzip'
def create(self, filename, base_image=None, ensure_empty_tmpdirs=None): """ Create WSL/Appx archive :param string filename: archive file name :param string base_image: not-supported :param string ensure_empty_tmpdirs: not-supported """ exclude_list = Defaults.\ get_exclude_list_for_root_data_sync() + Defaults.\ get_exclude_list_from_custom_exclude_files(self.root_dir) exclude_list.append('boot') exclude_list.append('dev') exclude_list.append('sys') exclude_list.append('proc') # The C code of WSL-DistroLauncher harcodes the name for the # root tarball to be install.tar.gz. Thus we have to use this # name for the root tarball archive_file_name = os.sep.join( [self.meta_data_path, 'install.tar'] ) archive = ArchiveTar( archive_file_name ) archive_file_name = archive.create( self.root_dir, exclude=exclude_list ) compressor = Compress(archive_file_name) archive_file_name = compressor.gzip() filemap_file = Temporary().new_file() with open(filemap_file.name, 'w') as filemap: filemap.write('[Files]{0}'.format(os.linesep)) for topdir, dirs, files in sorted(os.walk(self.meta_data_path)): for entry in sorted(dirs + files): if entry in files: mapfile = os.sep.join([topdir, entry]) mapfile_relative = os.path.relpath(mapfile, start=self.meta_data_path) log.info( 'Adding {0} to Appx filemap as relative path {1}'.format(mapfile, mapfile_relative) ) filemap.write( '"{0}" "{1}"{2}'.format( mapfile, mapfile_relative, os.linesep ) ) Command.run( ['appx', '-o', filename, '-f', filemap_file.name] ) return filename
def create_recovery_archive(self): """ Create a compressed recovery archive from the root tree for use with kiwi's recvoery system. The method creates additional data into the image root filesystem which is deleted prior to the creation of a new recovery data set """ # cleanup bash_comand = ['rm', '-f', self.root_dir + '/recovery.*'] Command.run(['bash', '-c', ' '.join(bash_comand)]) if not self.oemconfig['recovery']: return # recovery.tar log.info('Creating recovery tar archive') metadata = { 'archive_name': self.root_dir + '/recovery.tar', 'archive_filecount': self.root_dir + '/recovery.tar.files', 'archive_size': self.root_dir + '/recovery.tar.size', 'partition_size': self.root_dir + '/recovery.partition.size', 'partition_filesystem': self.root_dir + '/recovery.tar.filesystem' } recovery_archive = NamedTemporaryFile(delete=False) archive = ArchiveTar(filename=recovery_archive.name, create_from_file_list=False) archive.create(source_dir=self.root_dir, exclude=['dev', 'proc', 'sys'], options=[ '--numeric-owner', '--hard-dereference', '--preserve-permissions' ]) Command.run(['mv', recovery_archive.name, metadata['archive_name']]) # recovery.tar.filesystem recovery_filesystem = self.xml_state.build_type.get_filesystem() with open(metadata['partition_filesystem'], 'w') as partfs: partfs.write('%s' % recovery_filesystem) log.info('--> Recovery partition filesystem: %s', recovery_filesystem) # recovery.tar.files bash_comand = ['tar', '-tf', metadata['archive_name'], '|', 'wc', '-l'] tar_files_call = Command.run(['bash', '-c', ' '.join(bash_comand)]) tar_files_count = int(tar_files_call.output.rstrip('\n')) with open(metadata['archive_filecount'], 'w') as files: files.write('%d\n' % tar_files_count) log.info('--> Recovery file count: %d files', tar_files_count) # recovery.tar.size recovery_archive_size_bytes = os.path.getsize(metadata['archive_name']) with open(metadata['archive_size'], 'w') as size: size.write('%d' % recovery_archive_size_bytes) log.info('--> Recovery uncompressed size: %d mbytes', int(recovery_archive_size_bytes / 1048576)) # recovery.tar.gz log.info('--> Compressing recovery archive') compress = Compress(self.root_dir + '/recovery.tar') compress.gzip() # recovery.partition.size recovery_archive_gz_size_mbytes = int( os.path.getsize(metadata['archive_name'] + '.gz') / 1048576) recovery_partition_mbytes = recovery_archive_gz_size_mbytes \ + Defaults.get_recovery_spare_mbytes() with open(metadata['partition_size'], 'w') as gzsize: gzsize.write('%d' % recovery_partition_mbytes) log.info('--> Recovery partition size: %d mbytes', recovery_partition_mbytes) # delete recovery archive if inplace recovery is requested # In this mode the recovery archive is created at install time # and not at image creation time. However the recovery metadata # is preserved in order to be able to check if enough space # is available on the disk to create the recovery archive. if self.oemconfig['recovery_inplace']: log.info('--> Inplace recovery requested, deleting archive') Path.wipe(metadata['archive_name'] + '.gz')
class TestCompress(object): @patch('os.path.exists') def setup(self, mock_exists): mock_exists.return_value = True self.compress = Compress('some-file', True) @raises(KiwiFileNotFound) def test_source_file_not_found(self): Compress('some-file') @patch('kiwi.command.Command.run') def test_xz(self, mock_command): assert self.compress.xz() == 'some-file.xz' mock_command.assert_called_once_with( ['xz', '-f', '--threads=0', '--keep', 'some-file']) assert self.compress.compressed_filename == 'some-file.xz' @patch('kiwi.command.Command.run') def test_xz_with_custom_options(self, mock_command): assert self.compress.xz(options=['foo', 'bar']) == 'some-file.xz' mock_command.assert_called_once_with( ['xz', '-f', 'foo', 'bar', '--keep', 'some-file']) assert self.compress.compressed_filename == 'some-file.xz' @patch('kiwi.command.Command.run') def test_gzip(self, mock_command): assert self.compress.gzip() == 'some-file.gz' mock_command.assert_called_once_with( ['gzip', '-f', '-9', '--keep', 'some-file']) assert self.compress.compressed_filename == 'some-file.gz' @patch('kiwi.command.Command.run') @patch('kiwi.utils.compress.NamedTemporaryFile') @patch('kiwi.utils.compress.Compress.get_format') def test_uncompress(self, mock_format, mock_temp, mock_command): mock_format.return_value = 'xz' self.compress.uncompress() mock_command.assert_called_once_with(['xz', '-d', 'some-file']) assert self.compress.uncompressed_filename == 'some-file' @patch('kiwi.command.Command.run') @patch('kiwi.utils.compress.NamedTemporaryFile') @patch('kiwi.utils.compress.Compress.get_format') def test_uncompress_temporary(self, mock_format, mock_temp, mock_command): tempfile = mock.Mock() tempfile.name = 'tempfile' mock_temp.return_value = tempfile mock_format.return_value = 'xz' self.compress.uncompress(temporary=True) mock_command.assert_called_once_with( ['bash', '-c', 'xz -c -d some-file > tempfile']) assert self.compress.uncompressed_filename == 'tempfile' @raises(KiwiCompressionFormatUnknown) @patch('kiwi.utils.compress.Compress.get_format') def test_uncompress_unknown_format(self, mock_format): mock_format.return_value = None self.compress.uncompress() @patch('kiwi.path.Path.which') def test_get_format(self, mock_which): mock_which.return_value = 'ziptool' xz = Compress('../data/xz_data.xz') assert xz.get_format() == 'xz' gzip = Compress('../data/gz_data.gz') assert gzip.get_format() == 'gzip' @patch('kiwi.logger.log.debug') @patch('kiwi.command.Command.run') def test_get_format_invalid_format(self, mock_run, mock_log): mock_run.side_effect = ValueError("nothing") invalid = Compress("../data/gz_data.gz") invalid.supported_zipper = ["mock_zip"] assert invalid.get_format() is None mock_run.assert_called_once_with( ['mock_zip', '-l', '../data/gz_data.gz']) mock_log.assert_called_once_with( 'Error running "mock_zip -l ../data/gz_data.gz", got a' ' ValueError: nothing')
class TestCompress(object): @patch('os.path.exists') def setup(self, mock_exists): mock_exists.return_value = True self.compress = Compress('some-file', True) @raises(KiwiFileNotFound) def test_source_file_not_found(self): Compress('some-file') @patch('kiwi.command.Command.run') def test_xz(self, mock_command): assert self.compress.xz() == 'some-file.xz' mock_command.assert_called_once_with( [ 'xz', '-f', '--threads=0', '--keep', 'some-file' ] ) assert self.compress.compressed_filename == 'some-file.xz' @patch('kiwi.command.Command.run') def test_xz_with_custom_options(self, mock_command): assert self.compress.xz(options=['foo', 'bar']) == 'some-file.xz' mock_command.assert_called_once_with( [ 'xz', '-f', 'foo', 'bar', '--keep', 'some-file' ] ) assert self.compress.compressed_filename == 'some-file.xz' @patch('kiwi.command.Command.run') def test_gzip(self, mock_command): assert self.compress.gzip() == 'some-file.gz' mock_command.assert_called_once_with( ['gzip', '-f', '-9', '--keep', 'some-file'] ) assert self.compress.compressed_filename == 'some-file.gz' @patch('kiwi.command.Command.run') @patch('kiwi.utils.compress.NamedTemporaryFile') @patch('kiwi.utils.compress.Compress.get_format') def test_uncompress(self, mock_format, mock_temp, mock_command): mock_format.return_value = 'xz' self.compress.uncompress() mock_command.assert_called_once_with( ['xz', '-d', 'some-file'] ) assert self.compress.uncompressed_filename == 'some-file' @patch('kiwi.command.Command.run') @patch('kiwi.utils.compress.NamedTemporaryFile') @patch('kiwi.utils.compress.Compress.get_format') def test_uncompress_temporary(self, mock_format, mock_temp, mock_command): tempfile = mock.Mock() tempfile.name = 'tempfile' mock_temp.return_value = tempfile mock_format.return_value = 'xz' self.compress.uncompress(temporary=True) mock_command.assert_called_once_with( ['bash', '-c', 'xz -c -d some-file > tempfile'] ) assert self.compress.uncompressed_filename == 'tempfile' @raises(KiwiCompressionFormatUnknown) @patch('kiwi.utils.compress.Compress.get_format') def test_uncompress_unknown_format(self, mock_format): mock_format.return_value = None self.compress.uncompress() @patch('kiwi.path.Path.which') def test_get_format(self, mock_which): mock_which.return_value = 'ziptool' xz = Compress('../data/xz_data.xz') assert xz.get_format() == 'xz' gzip = Compress('../data/gz_data.gz') assert gzip.get_format() == 'gzip'
def create_recovery_archive(self): """ Create a compressed recovery archive from the root tree for use with kiwi's recvoery system. The method creates additional data into the image root filesystem which is deleted prior to the creation of a new recovery data set """ # cleanup bash_comand = [ 'rm', '-f', self.root_dir + '/recovery.*' ] Command.run(['bash', '-c', ' '.join(bash_comand)]) if not self.oemconfig['recovery']: return # recovery.tar log.info('Creating recovery tar archive') metadata = { 'archive_name': self.root_dir + '/recovery.tar', 'archive_filecount': self.root_dir + '/recovery.tar.files', 'archive_size': self.root_dir + '/recovery.tar.size', 'partition_size': self.root_dir + '/recovery.partition.size', 'partition_filesystem': self.root_dir + '/recovery.tar.filesystem' } recovery_archive = NamedTemporaryFile( delete=False ) archive = ArchiveTar( filename=recovery_archive.name, create_from_file_list=False ) archive.create( source_dir=self.root_dir, exclude=['dev', 'proc', 'sys'], options=[ '--numeric-owner', '--hard-dereference', '--preserve-permissions' ] ) Command.run( ['mv', recovery_archive.name, metadata['archive_name']] ) # recovery.tar.filesystem recovery_filesystem = self.xml_state.build_type.get_filesystem() with open(metadata['partition_filesystem'], 'w') as partfs: partfs.write('%s' % recovery_filesystem) log.info( '--> Recovery partition filesystem: %s', recovery_filesystem ) # recovery.tar.files bash_comand = [ 'tar', '-tf', metadata['archive_name'], '|', 'wc', '-l' ] tar_files_call = Command.run( ['bash', '-c', ' '.join(bash_comand)] ) tar_files_count = int(tar_files_call.output.rstrip('\n')) with open(metadata['archive_filecount'], 'w') as files: files.write('%d\n' % tar_files_count) log.info( '--> Recovery file count: %d files', tar_files_count ) # recovery.tar.size recovery_archive_size_bytes = os.path.getsize(metadata['archive_name']) with open(metadata['archive_size'], 'w') as size: size.write('%d' % recovery_archive_size_bytes) log.info( '--> Recovery uncompressed size: %d mbytes', int(recovery_archive_size_bytes / 1048576) ) # recovery.tar.gz log.info('--> Compressing recovery archive') compress = Compress(self.root_dir + '/recovery.tar') compress.gzip() # recovery.partition.size recovery_archive_gz_size_mbytes = int( os.path.getsize(metadata['archive_name'] + '.gz') / 1048576 ) recovery_partition_mbytes = recovery_archive_gz_size_mbytes \ + Defaults.get_recovery_spare_mbytes() with open(metadata['partition_size'], 'w') as gzsize: gzsize.write('%d' % recovery_partition_mbytes) log.info( '--> Recovery partition size: %d mbytes', recovery_partition_mbytes ) # delete recovery archive if inplace recovery is requested # In this mode the recovery archive is created at install time # and not at image creation time. However the recovery metadata # is preserved in order to be able to check if enough space # is available on the disk to create the recovery archive. if self.oemconfig['recovery_inplace']: log.info( '--> Inplace recovery requested, deleting archive' ) Path.wipe(metadata['archive_name'] + '.gz')