class TestMigrationConfig(object): @patch.object(Defaults, 'get_migration_config_file') @patch.object(Defaults, 'get_system_migration_custom_config_file') def setup(self, mock_get_system_migration_config_custom_file, mock_get_migration_config_file): mock_get_migration_config_file.return_value = \ '../data/migration-config.yml' mock_get_system_migration_config_custom_file.return_value = \ '../data/custom-migration-config.yml' self.config = MigrationConfig() def test_get_migration_product(self): assert self.config.get_migration_product() == 'SLES/15/x86_64' def test_get_preserve_udev_rules_list(self): assert self.config.get_preserve_udev_rules_list() == [ '/etc/udev/rules.d/a.rules', '/etc/udev/rules.d/b.rules' ] @patch('suse_migration_services.logger.log.error') def test_get_migration_product_targets(self, mock_error): self.config.config_data = {'not_migration_product': 'another_info'} with raises(DistMigrationProductNotFoundException): self.config.get_migration_product() assert mock_error.called @patch.object(MigrationConfig, '_write_config_file') @patch('suse_migration_services.logger.log.info') def test_update_migration_config_file( self, mock_info, mock_write_config_file, ): self.config.update_migration_config_file() assert self.config.get_migration_product() == 'SLES/15.1/x86_64' assert self.config.is_debug_requested() is True assert mock_info.called def test_is_zypper_migration_plugin_requested(self): assert self.config.is_zypper_migration_plugin_requested() is True def test_is_debug_requested(self): assert self.config.is_debug_requested() is False @patch('yaml.dump') def test_write_config_file(self, mock_yaml_dump): with patch('builtins.open', create=True) as mock_open: mock_open.return_value = MagicMock(spec=io.IOBase) file_handle = mock_open.return_value.__enter__.return_value self.config._write_config_file() mock_open.assert_called_once_with( self.config.migration_config_file, 'w') mock_yaml_dump.assert_called_once_with(self.config.config_data, file_handle, default_flow_style=False)
def main(): """ DistMigration run zypper based migration Call zypper migration plugin and migrate the system. The output of the call is logged on the system to migrate """ root_path = Defaults.get_system_root_path() try: log.info('Running migrate service') migration_config = MigrationConfig() if migration_config.is_zypper_migration_plugin_requested(): bash_command = ' '.join([ 'zypper', 'migration', '--non-interactive', '--gpg-auto-import-keys', '--no-selfupdate', '--auto-agree-with-licenses', '--allow-vendor-change', '--strict-errors-dist-migration', '--replacefiles', '--product', migration_config.get_migration_product(), '--root', root_path, '&>>', Defaults.get_migration_log_file() ]) Command.run(['bash', '-c', bash_command]) else: bash_command = ' '.join([ 'zypper', '--non-interactive', '--gpg-auto-import-keys', '--root', root_path, 'dup', '--auto-agree-with-licenses', '--allow-vendor-change', '--replacefiles', '&>>', Defaults.get_migration_log_file() ]) zypper_call = Command.run(['bash', '-c', bash_command], raise_on_error=False) if zypper_has_failed(zypper_call.returncode): raise DistMigrationCommandException( '{0} failed with: {1}: {2}'.format(bash_command, zypper_call.output, zypper_call.error)) except Exception as issue: etc_issue_path = os.sep.join([root_path, 'etc/issue']) log_path_migrated_system = os.sep + os.path.relpath( Defaults.get_migration_log_file(), root_path) with open(etc_issue_path, 'w') as issue_file: issue_file.write( 'Migration has failed, for further details see {0}'.format( log_path_migrated_system)) log.error('migrate service failed with {0}'.format(issue)) raise DistMigrationZypperException( 'Migration failed with {0}'.format(issue))
class TestMigrationConfig(object): @patch.object(Defaults, 'get_migration_config_file') @patch.object(Defaults, 'get_system_migration_custom_config_file') def setup( self, mock_get_system_migration_config_custom_file, mock_get_migration_config_file ): mock_get_migration_config_file.return_value = \ '../data/migration-config.yml' mock_get_system_migration_config_custom_file.return_value = \ '../data/custom-migration-config.yml' self.config = MigrationConfig() @patch.object(Defaults, 'get_os_release') @patch.object(Defaults, 'get_system_root_path') def test_get_migration_product_auto_detected( self, mock_get_system_root_path, mock_get_os_release ): os_release_tuple = namedtuple( 'OSRelease', [ 'name', 'version', 'version_id', 'pretty_name', 'id', 'id_like', 'ansi_color', 'cpe_name' ] ) os_release_result = os_release_tuple( name='SLES', version='15-SP1', version_id='15.1', pretty_name='SUSE Linux Enterprise Server 15 SP1', id='sles', id_like='suse', ansi_color='0;32', cpe_name='cpe:/o:suse:sles:15:sp1' ) mock_get_system_root_path.return_value = '../data' mock_get_os_release.return_value = os_release_result assert self.config.get_migration_product() == 'SLES/15.1/x86_64' def test_get_preserve_udev_rules_list(self): assert self.config.get_preserve_udev_rules_list() == [ '/etc/udev/rules.d/a.rules', '/etc/udev/rules.d/b.rules' ] @patch.object(Defaults, 'get_os_release') @patch.object(SUSEBaseProduct, 'get_tag') @patch.object(Defaults, 'get_system_root_path') def test_get_migration_product_targets( self, mock_get_system_root_path, mock_get_product_name, mock_get_os_release ): os_release_tuple = namedtuple( 'OSRelease', [ 'name', 'version', 'version_id', 'pretty_name', 'id', 'id_like', 'ansi_color', 'cpe_name' ] ) os_release_result = os_release_tuple( name='SLES', version='15-SP1', version_id='15.1', pretty_name='SUSE Linux Enterprise Server 15 SP1', id='sles', id_like='suse', ansi_color='0;32', cpe_name='cpe:/o:suse:sles:15:sp1' ) mock_get_system_root_path.return_value = '../data' mock_get_os_release.return_value = os_release_result mock_get_product_name.side_effect = Exception self.config.config_data = {'not_migration_product': 'another_info'} with raises(DistMigrationProductNotFoundException): self.config.get_migration_product() @patch.object(Defaults, 'get_os_release') @patch.object(SUSEBaseProduct, 'get_product_name') @patch.object(Defaults, 'get_system_root_path') @patch.object(MigrationConfig, '_write_config_file') def test_update_migration_config_file_no_autodetect( self, mock_write_config_file, mock_get_system_root_path, mock_get_product_name, mock_get_os_release ): os_release_tuple = namedtuple( 'OSRelease', [ 'name', 'version', 'version_id', 'pretty_name', 'id', 'id_like', 'ansi_color', 'cpe_name' ] ) os_release_result = os_release_tuple( name='SLES', version='15-SP1', version_id='15.1', pretty_name='SUSE Linux Enterprise Server 15 SP1', id='sles', id_like='suse', ansi_color='0;32', cpe_name='cpe:/o:suse:sles:15:sp1' ) mock_get_os_release.return_value = os_release_result mock_get_system_root_path.return_value = '../data' mock_get_product_name.return_value = None self.config.update_migration_config_file() assert self.config.get_migration_product() == 'SLES/15.1/x86_64' assert self.config.is_debug_requested() is True def test_is_zypper_migration_plugin_requested(self): assert self.config.is_zypper_migration_plugin_requested() is True def test_is_debug_requested(self): assert self.config.is_debug_requested() is False @patch('yaml.dump') def test_write_config_file(self, mock_yaml_dump): with patch('builtins.open', create=True) as mock_open: mock_open.return_value = MagicMock(spec=io.IOBase) file_handle = mock_open.return_value.__enter__.return_value self.config._write_config_file() mock_open.assert_called_once_with( self.config.migration_config_file, 'w' ) mock_yaml_dump.assert_called_once_with( self.config.config_data, file_handle, default_flow_style=False ) @patch.object(MigrationConfig, '_write_config_file') @patch.object(Defaults, 'get_migration_config_file') @patch.object(Defaults, 'get_system_migration_custom_config_file') def test_update_migration_config_file_empty( self, mock_get_system_migration_config_custom_file, mock_get_migration_config_file, mock_write_config_file, ): mock_get_migration_config_file.return_value = \ '../data/migration-config.yml' mock_get_system_migration_config_custom_file.return_value = \ '../data/custom-migration-config-empty.yml' self.config = MigrationConfig() self.config.update_migration_config_file() @patch.object(MigrationConfig, '_write_config_file') @patch.object(Defaults, 'get_migration_config_file') @patch.object(Defaults, 'get_system_migration_custom_config_file') def test_update_migration_config_file_just_comments( self, mock_get_system_migration_config_custom_file, mock_get_migration_config_file, mock_write_config_file, ): mock_get_migration_config_file.return_value = \ '../data/migration-config.yml' mock_get_system_migration_config_custom_file.return_value = \ '../data/custom-migration-config-just-comments.yml' self.config = MigrationConfig() self.config.update_migration_config_file() @patch.object(MigrationConfig, '_write_config_file') @patch.object(Defaults, 'get_migration_config_file') @patch.object(Defaults, 'get_system_migration_custom_config_file') def test_update_migration_config_file_slightly_broken( self, mock_get_system_migration_config_custom_file, mock_get_migration_config_file, mock_write_config_file, ): mock_get_migration_config_file.return_value = \ '../data/migration-config.yml' mock_get_system_migration_config_custom_file.return_value = \ '../data/custom-migration-config-corrupt-string.yml' self.config = MigrationConfig() with raises(DistMigrationConfigDataException): self.config.update_migration_config_file() @patch.object(MigrationConfig, '_write_config_file') @patch.object(Defaults, 'get_migration_config_file') @patch.object(Defaults, 'get_system_migration_custom_config_file') def test_update_migration_config_file_very_broken( self, mock_get_system_migration_config_custom_file, mock_get_migration_config_file, mock_write_config_file, ): mock_get_migration_config_file.return_value = \ '../data/migration-config.yml' mock_get_system_migration_config_custom_file.return_value = \ '../data/custom-migration-config-corrupt-mess.yml' self.config = MigrationConfig() with raises(DistMigrationConfigDataException): self.config.update_migration_config_file() @patch.object(MigrationConfig, '_write_config_file') @patch.object(Defaults, 'get_migration_config_file') @patch.object(Defaults, 'get_system_migration_custom_config_file') def test_update_migration_config_file_violates_schema( self, mock_get_system_migration_config_custom_file, mock_get_migration_config_file, mock_write_config_file, ): mock_get_migration_config_file.return_value = \ '../data/migration-config.yml' mock_get_system_migration_config_custom_file.return_value = \ '../data/custom-migration-config-violates-schema.yml' self.config = MigrationConfig() with raises(DistMigrationConfigDataException): self.config.update_migration_config_file()