def clean_leftovers(self) -> None: """ Cleans package manager related data not needed in the resulting image such as custom macros """ Rpm(self.root_dir, Defaults.get_custom_rpm_image_macro_name()).wipe_config()
def setup_package_database_configuration(self) -> None: """ Setup rpm macros for bootstrapping and image building 1. Create the rpm image macro which persists during the build 2. Create the rpm bootstrap macro to make sure for bootstrapping the rpm database location matches the host rpm database setup. This macro only persists during the bootstrap phase. If the image was already bootstrapped a compat link is created instead. 3. Create zypper compat link """ rpmdb = RpmDataBase( self.root_dir, Defaults.get_custom_rpm_image_macro_name() ) if self.locale: rpmdb.set_macro_from_string(self.locale[0]) rpmdb.write_config() rpmdb = RpmDataBase(self.root_dir) if rpmdb.has_rpm(): rpmdb.link_database_to_host_path() else: rpmdb.set_database_to_host_path() # Zypper compat code: # # Manually adding the compat link /var/lib/rpm that points to the # rpmdb location as it is configured in the host rpm setup. The # host rpm setup is taken into account because import_trusted_keys # is called during the bootstrap phase where rpm (respectively zypper) # is called from the host # # Usually it is expected that the package manager reads the # signing keys from the rpm database setup provisioned by rpm # itself (macro level) but zypper doesn't take the rpm macro # setup into account and relies on a hard coded path which we # can only provide as a symlink. # # That symlink is usually created by the rpm package when it gets # installed. However at that early phase when we import the # signing keys no rpm is installed yet nor any symlink exists. # Thus we have to create it here and hope to get rid of it in the # future. # # For further details on the motivation in zypper please # refer to bsc#1112357 rpmdb.init_database() image_rpm_compat_link = '/var/lib/rpm' host_rpm_dbpath = rpmdb.rpmdb_host.expand_query('%_dbpath') if host_rpm_dbpath != image_rpm_compat_link: Path.create( self.root_dir + os.path.dirname(image_rpm_compat_link) ) Command.run( [ 'ln', '-s', '--no-target-directory', ''.join(['../..', host_rpm_dbpath]), self.root_dir + image_rpm_compat_link ], raise_on_error=False )
def clean_leftovers(self) -> None: """ Cleans package manager related data not needed in the resulting image such as custom macros """ Rpm(self.root_dir, Defaults.get_custom_rpm_image_macro_name()).wipe_config() id_file = os.path.normpath( os.sep.join([self.root_dir, self.anonymousId_file])) if os.path.exists(id_file): os.unlink(id_file)
def setup_package_database_configuration(self): """ Setup rpm macros for bootstrapping and image building 1. Create the rpm image macro which persists during the build 2. Create the rpm bootstrap macro to make sure for bootstrapping the rpm database location matches the host rpm database setup. This macro only persists during the bootstrap phase """ rpmdb = RpmDataBase(self.root_dir, Defaults.get_custom_rpm_image_macro_name()) if self.locale: rpmdb.set_macro_from_string(self.locale[0]) rpmdb.write_config() RpmDataBase(self.root_dir).set_database_to_host_path()
def setup_package_database_configuration(self): """ Setup rpm macros for bootstrapping and image building 1. Create the rpm image macro which persists during the build 2. Create the rpm bootstrap macro to make sure for bootstrapping the rpm database location matches the host rpm database setup. This macro only persists during the bootstrap phase. If the image was already bootstrapped a compat link is created instead. """ rpmdb = RpmDataBase(self.root_dir, Defaults.get_custom_rpm_image_macro_name()) if self.locale: rpmdb.set_macro_from_string(self.locale[0]) rpmdb.write_config() rpmdb = RpmDataBase(self.root_dir) if rpmdb.has_rpm(): rpmdb.link_database_to_host_path() else: rpmdb.set_database_to_host_path() # SUSE compat code: # # Manually adding the compat link /var/lib/rpm that points to the # rpmdb location as it is configured in the host rpm setup. DNF makes # use of the host setup to bootstrap or to read the signing keys # from the rpm database setup provisioned by rpm itself (macro level). # It assumes the host setup is the default for the system being built. # # For SUSE this is causing a mismatch as the host setup is not the RPM # default (/var/lib/rpm) and SUSE distros proactively relocate the rpm # database from the default location to a custom one when the # rpm package and related macros are installed for the first time. rpmdb.init_database() image_rpm_compat_link = '/var/lib/rpm' host_rpm_dbpath = rpmdb.rpmdb_host.expand_query('%_dbpath') if host_rpm_dbpath != image_rpm_compat_link: Path.create(self.root_dir + os.path.dirname(image_rpm_compat_link)) Command.run([ 'ln', '-s', '--no-target-directory', ''.join([ '../..', host_rpm_dbpath ]), self.root_dir + image_rpm_compat_link ], raise_on_error=False)
def process(self): # noqa: C901 """ Prepare and install a new system for chroot access """ self.manual = Help() if self._help(): return Privileges.check_for_root_permissions() self.load_xml_description(self.command_args['--description']) abs_root_path = os.path.abspath(self.command_args['--root']) prepare_checks = self.checks_before_command_args prepare_checks.update( {'check_target_directory_not_in_shared_cache': [abs_root_path]}) self.run_checks(prepare_checks) if self.command_args['--ignore-repos']: self.xml_state.delete_repository_sections() elif self.command_args['--ignore-repos-used-for-build']: self.xml_state.delete_repository_sections_used_for_build() if self.command_args['--set-repo']: self.xml_state.set_repository( *self.sextuple_token(self.command_args['--set-repo'])) if self.command_args['--add-repo']: for add_repo in self.command_args['--add-repo']: self.xml_state.add_repository(*self.sextuple_token(add_repo)) if self.command_args['--set-container-tag']: self.xml_state.set_container_config_tag( self.command_args['--set-container-tag']) if self.command_args['--add-container-label']: for add_label in self.command_args['--add-container-label']: try: (name, value) = add_label.split('=', 1) self.xml_state.add_container_config_label(name, value) except Exception: log.warning('Container label {0} ignored. Invalid format: ' 'expected labelname=value'.format(add_label)) if self.command_args['--set-container-derived-from']: self.xml_state.set_derived_from_image_uri( self.command_args['--set-container-derived-from']) self.run_checks(self.checks_after_command_args) log.info('Preparing system') system = SystemPrepare(self.xml_state, abs_root_path, self.command_args['--allow-existing-root']) manager = system.setup_repositories(self.command_args['--clear-cache'], self.command_args['--signing-key']) system.install_bootstrap(manager, self.command_args['--add-bootstrap-package']) system.install_system(manager) if self.command_args['--add-package']: system.install_packages(manager, self.command_args['--add-package']) if self.command_args['--delete-package']: system.delete_packages(manager, self.command_args['--delete-package']) profile = Profile(self.xml_state) defaults = Defaults() defaults.to_profile(profile) setup = SystemSetup(self.xml_state, abs_root_path) setup.import_shell_environment(profile) setup.import_description() setup.import_overlay_files() setup.import_image_identifier() setup.setup_groups() setup.setup_users() setup.setup_keyboard_map() setup.setup_locale() setup.setup_plymouth_splash() setup.setup_timezone() setup.setup_permissions() # make sure manager instance is cleaned up now del manager # setup permanent image repositories after cleanup setup.import_repositories_marked_as_imageinclude() setup.call_config_script() # handle uninstall package requests, gracefully uninstall # with dependency cleanup system.pinch_system(force=False) # handle delete package requests, forced uninstall without # any dependency resolution system.pinch_system(force=True) # delete any custom rpm macros created Rpm(abs_root_path, Defaults.get_custom_rpm_image_macro_name()).wipe_config() # make sure system instance is cleaned up now del system
def process(self): # noqa: C901 """ Build a system image from the specified description. The build command combines the prepare and create commands """ self.manual = Help() if self._help(): return Privileges.check_for_root_permissions() abs_target_dir_path = os.path.abspath( self.command_args['--target-dir'] ) build_dir = os.sep.join([abs_target_dir_path, 'build']) image_root = os.sep.join([build_dir, 'image-root']) Path.create(build_dir) if not self.global_args['--logfile']: log.set_logfile( os.sep.join([abs_target_dir_path, 'build', 'image-root.log']) ) self.load_xml_description( self.command_args['--description'] ) self.runtime_checker.check_minimal_required_preferences() self.runtime_checker.check_efi_mode_for_disk_overlay_correctly_setup() self.runtime_checker.check_boot_description_exists() self.runtime_checker.check_consistent_kernel_in_boot_and_system_image() self.runtime_checker.check_docker_tool_chain_installed() self.runtime_checker.check_volume_setup_defines_multiple_fullsize_volumes() self.runtime_checker.check_volume_setup_has_no_root_definition() self.runtime_checker.check_volume_label_used_with_lvm() self.runtime_checker.check_xen_uniquely_setup_as_server_or_guest() self.runtime_checker.check_target_directory_not_in_shared_cache( abs_target_dir_path ) self.runtime_checker.check_mediacheck_only_for_x86_arch() self.runtime_checker.check_dracut_module_for_live_iso_in_package_list() self.runtime_checker.check_dracut_module_for_disk_overlay_in_package_list() self.runtime_checker.check_dracut_module_for_disk_oem_in_package_list() self.runtime_checker.check_dracut_module_for_oem_install_in_package_list() if self.command_args['--ignore-repos']: self.xml_state.delete_repository_sections() elif self.command_args['--ignore-repos-used-for-build']: self.xml_state.delete_repository_sections_used_for_build() if self.command_args['--set-repo']: self.xml_state.set_repository( *self.sextuple_token(self.command_args['--set-repo']) ) if self.command_args['--add-repo']: for add_repo in self.command_args['--add-repo']: self.xml_state.add_repository( *self.sextuple_token(add_repo) ) if self.command_args['--set-container-tag']: self.xml_state.set_container_config_tag( self.command_args['--set-container-tag'] ) if self.command_args['--add-container-label']: for add_label in self.command_args['--add-container-label']: try: (name, value) = add_label.split('=', 1) self.xml_state.add_container_config_label(name, value) except Exception: log.warning( 'Container label {0} ignored. Invalid format: ' 'expected labelname=value'.format(add_label) ) if self.command_args['--set-container-derived-from']: self.xml_state.set_derived_from_image_uri( self.command_args['--set-container-derived-from'] ) self.runtime_checker.check_repositories_configured() self.runtime_checker.check_image_include_repos_publicly_resolvable() log.info('Preparing new root system') system = SystemPrepare( self.xml_state, image_root, self.command_args['--allow-existing-root'] ) manager = system.setup_repositories( self.command_args['--clear-cache'], self.command_args['--signing-key'] ) system.install_bootstrap(manager) system.install_system( manager ) if self.command_args['--add-package']: system.install_packages( manager, self.command_args['--add-package'] ) if self.command_args['--delete-package']: system.delete_packages( manager, self.command_args['--delete-package'] ) profile = Profile(self.xml_state) defaults = Defaults() defaults.to_profile(profile) setup = SystemSetup( self.xml_state, image_root ) setup.import_shell_environment(profile) setup.import_description() setup.import_overlay_files() setup.import_image_identifier() setup.setup_groups() setup.setup_users() setup.setup_keyboard_map() setup.setup_locale() setup.setup_plymouth_splash() setup.setup_timezone() setup.setup_permissions() # make sure manager instance is cleaned up now del manager # setup permanent image repositories after cleanup setup.import_repositories_marked_as_imageinclude() setup.call_config_script() # handle uninstall package requests, gracefully uninstall # with dependency cleanup system.pinch_system(force=False) # handle delete package requests, forced uninstall without # any dependency resolution system.pinch_system(force=True) # delete any custom rpm macros created Rpm( image_root, Defaults.get_custom_rpm_image_macro_name() ).wipe_config() # make sure system instance is cleaned up now del system setup.call_image_script() # make sure setup instance is cleaned up now del setup log.info('Creating system image') image_builder = ImageBuilder( self.xml_state, abs_target_dir_path, image_root, custom_args={ 'signing_keys': self.command_args['--signing-key'], 'xz_options': self.runtime_config.get_xz_options() } ) result = image_builder.create() result.print_results() result.dump( os.sep.join([abs_target_dir_path, 'kiwi.result']) )