def _get_boot_image_output_file_format(self): """ The initrd output file format varies between the different Linux distributions. Tools like lsinitrd, and also grub2 rely on the initrd output file to be in that format. Thus kiwi should use the same file format to stay compatible with the distributions. The format is determined by the outfile format used in the dracut initrd tool which is the standard on all major linux distributions. """ if self.xml_state.get_initrd_system() == 'kiwi': # The custom kiwi initrd system is used only on SUSE systems. # The initrd environment does not provide dracut and thus the # outfile format cannot be determined. on SUSE systems the # initrd format is different than on upstream and therefore # it can be explicitly specified. Note that the custom initrd # system will become obsolete in the future. default_outfile_format = 'initrd-{kernel_version}' else: default_outfile_format = 'initramfs-{kernel_version}.img' dracut_tool = Path.which('dracut', root_dir=self.boot_root_directory, access_mode=os.X_OK) if dracut_tool: outfile_expression = r'outfile="/boot/(init.*\$kernel.*)"' with open(dracut_tool) as dracut: matches = re.findall(outfile_expression, dracut.read()) if matches: return matches[0].replace('$kernel', '{kernel_version}') log.warning('Could not detect dracut output file format') log.warning('Using default initrd file name format {0}'.format( default_outfile_format)) return default_outfile_format
def umount(self, raise_on_busy: bool = True) -> bool: """ Umount by the mountpoint directory Wait up to 10sec trying to umount. If the resource stays busy the call will raise an exception unless raise_on_busy is set to False. In case the umount failed and raise_on_busy is set to False, the method returns False to indicate the error condition. :return: True or False :rtype: bool """ if self.is_mounted(): umounted_successfully = False for busy in range(0, 10): try: Command.run(['umount', self.mountpoint]) umounted_successfully = True break except Exception: log.warning('%d umount of %s failed, try again in 1sec', busy, self.mountpoint) time.sleep(1) if not umounted_successfully: if raise_on_busy: lsof = Path.which('lsof', access_mode=os.X_OK) if lsof: open_files = Command.run( [lsof, '+c', '0', self.mountpoint], raise_on_error=False) open_files_info = 'Open files status:{0}{1}'.format( os.linesep, open_files.output) else: open_files_info = 'For further details install: lsof' message = dedent('''\n Failed to umount: {0}. Your build host system is in an inconsistent state. The cleanup of the created resource was not possible because it is still busy. This resource and all nested resources stays active on your host and needs a manual cleanup. Please do not use the intermediate state of the image files created so far. There is no guarantee that the produced results are valid. {1} ''') raise KiwiUmountBusyError( message.format(self.mountpoint, open_files_info)) else: log.warning('{0} still busy at {1}'.format( self.mountpoint, type(self).__name__)) # skip removing the mountpoint directory return False return True
def check_syslinux_installed_if_isolinux_is_used(self) -> None: """ ISO images that are configured to use isolinux requires the host to provide a set of syslinux binaries. """ message = dedent('''\n Required syslinux module(s) not found The ISO image build for this image setup uses isolinux and therefore requires the syslinux modules to be available on the build host. Please make sure your build host has the syslinux package installed. ''') firmware = FirmWare(self.xml_state) if Defaults.is_x86_arch( Defaults.get_platform_name() ) and not firmware.efi_mode(): image_builds_iso = False build_type = self.xml_state.get_build_type_name() if build_type == 'iso': image_builds_iso = True elif build_type == 'oem': install_iso = self.xml_state.build_type.get_installiso() install_stick = self.xml_state.build_type.get_installstick() if install_iso or install_stick: image_builds_iso = True if image_builds_iso: syslinux_check_file = Path.which( 'isohdpfx.bin', Defaults.get_syslinux_search_paths() ) if not syslinux_check_file: raise KiwiRuntimeError(message)
def _get_dracut_output_file_format(self): """ Unfortunately the dracut initrd output file format varies between the different Linux distributions. Tools like lsinitrd, and also grub2 rely on the initrd output file to be in that format. Thus when kiwi uses dracut the same file format should be used all over the place in order to stay compatible with what the distribution does """ default_outfile_format = 'initramfs-{kernel_version}.img' dracut_search_env = { 'PATH': os.sep.join([self.boot_root_directory, 'usr', 'bin']) } dracut_tool = Path.which('dracut', custom_env=dracut_search_env, access_mode=os.X_OK) if dracut_tool: outfile_expression = r'outfile="/boot/(init.*\$kernel.*)"' with open(dracut_tool) as dracut: outfile = re.findall(outfile_expression, dracut.read())[0] if outfile: return outfile.replace('$kernel', '{kernel_version}') log.warning('Could not detect dracut output file format') log.warning('Using default initrd file name format {0}'.format( default_outfile_format)) return default_outfile_format
def _get_shim_install(self): chroot_env = { 'PATH': os.sep.join([self.root_dir, 'usr', 'sbin']) } return Path.which( filename='shim-install', custom_env=chroot_env )
def _get_dracut_output_file_format(self): """ Unfortunately the dracut initrd output file format varies between the different Linux distributions. Tools like lsinitrd, and also grub2 rely on the initrd output file to be in that format. Thus when kiwi uses dracut the same file format should be used all over the place in order to stay compatible with what the distribution does """ default_outfile_format = 'initramfs-{kernel_version}.img' dracut_search_env = { 'PATH': os.sep.join([self.boot_root_directory, 'usr', 'bin']) } dracut_tool = Path.which( 'dracut', custom_env=dracut_search_env, access_mode=os.X_OK ) if dracut_tool: outfile_expression = r'outfile="/boot/(init.*\$kernel.*)"' with open(dracut_tool) as dracut: outfile = re.findall(outfile_expression, dracut.read())[0] if outfile: return outfile.replace('$kernel', '{kernel_version}') log.warning('Could not detect dracut output file format') log.warning('Using default initrd file name format {0}'.format( default_outfile_format )) return default_outfile_format
def setup_permissions(self): """ Check and Fix permissions using chkstat Call chkstat in system mode which reads /etc/sysconfig/security to determine the configured security level and applies the appropriate permission definitions from the /etc/permissions* files. It's possible to provide those files as overlay files in the image description to apply a certain permission setup when needed. Otherwise the default setup as provided on the package level applies. It's required that the image root system has chkstat installed. If not present KIWI skips this step and continuous with a warning. """ chkstat_search_env = { 'PATH': os.sep.join([self.root_dir, 'usr', 'bin']) } chkstat = Path.which('chkstat', custom_env=chkstat_search_env, access_mode=os.X_OK) if chkstat: log.info('Check/Fix File Permissions') Command.run( ['chroot', self.root_dir, 'chkstat', '--system', '--set']) else: log.warning( 'chkstat not found in image. File Permissions Check skipped')
def get_qemu_shared_path_setup_virtiofs(index: int, path: str, mount_tag: str) -> List[str]: virtiofsd_lookup_paths = ['/usr/lib', '/usr/libexec'] virtiofsd = Path.which('virtiofsd', virtiofsd_lookup_paths) if not virtiofsd: raise KiwiBoxPluginVirtioFsError( 'virtiofsd not found in: {0}'.format(virtiofsd_lookup_paths)) try: virtiofsd_process = subprocess.Popen([ virtiofsd, '--socket-path=/tmp/vhostqemu_{0}'.format(index), '-o', 'allow_root', '-o', 'source={0}'.format( os.path.abspath(path)), '-o', 'cache=always' ], close_fds=True) except Exception as issue: raise KiwiBoxPluginVirtioFsError( 'Failed to start virtiofsd: {0}'.format(issue)) VIRTIOFSD_PROCESS_LIST.append(virtiofsd_process) return [ '-chardev', 'socket,id=char{0},path=/tmp/vhostqemu_{0}'.format(index), '-device', 'vhost-user-fs-pci,queue-size=1024,chardev=char{0},tag={1}'.format( index, mount_tag) ]
def _get_grub2_mkconfig_tool(self): for grub_mkconfig_tool in ['grub2-mkconfig', 'grub-mkconfig']: grub_mkconfig_file_path = Path.which( grub_mkconfig_tool, root_dir=self.root_dir ) if grub_mkconfig_file_path: return grub_mkconfig_file_path
def test_which_not_found_log(self, mock_log, mock_exists, mock_env, mock_access): mock_env.return_value = '/usr/local/bin:/usr/bin:/bin' mock_exists.return_value = False assert Path.which('file') is None mock_log.assert_called_once_with( '"file": in paths "%s" exists: "False" mode match: not checked' % mock_env.return_value)
def test_which_not_found_log(self, mock_exists, mock_env, mock_access): mock_env.return_value = '/usr/local/bin:/usr/bin:/bin' mock_exists.return_value = False with self._caplog.at_level(logging.DEBUG): assert Path.which('file') is None print(self._caplog.text) assert '"file": in paths "{0}" exists: "False" mode match: ' 'not checked'.format(mock_env.return_value) in self._caplog.text
def test_which_not_found_for_mode_log(self, mock_exists, mock_env, mock_access): mock_env.return_value = '/usr/local/bin:/usr/bin:/bin' mock_exists.return_value = True mock_access.return_value = False with self._caplog.at_level(logging.DEBUG): assert Path.which('file', access_mode=os.X_OK) is None assert '"file": in paths "{0}" exists: "True" mode match: ' '"False"'.format(mock_env.return_value) in self._caplog.text
def test_which_not_found_for_mode_log(self, mock_log, mock_exists, mock_env, mock_access): mock_env.return_value = '/usr/local/bin:/usr/bin:/bin' mock_exists.return_value = True mock_access.return_value = False assert Path.which('file', access_mode=os.X_OK) is None mock_log.assert_called_once_with( '"file": in paths "%s" exists: "True" mode match: "False"' % mock_env.return_value)
def _get_yum_binary_name(self): """ Identify whether yum is 'yum' or 'yum-deprecated' :return: name of yum command """ yum_binary = 'yum' if Path.which(filename='yum-deprecated', access_mode=os.X_OK): yum_binary = 'yum-deprecated' return yum_binary
def _get_boot_image_output_file_format_from_dracut_code(self): dracut_tool = Path.which( 'dracut', root_dir=self.boot_root_directory, access_mode=os.X_OK ) if dracut_tool: outfile_expression = r'outfile="/boot/(init.*\$kernel.*)"' with open(dracut_tool) as dracut: matches = re.findall(outfile_expression, dracut.read()) if matches: return matches[0].replace('$kernel', '{kernel_version}')
def test_which_not_found_log( self, mock_log, mock_exists, mock_env, mock_access ): mock_env.return_value = '/usr/local/bin:/usr/bin:/bin' mock_exists.return_value = False assert Path.which('file') is None mock_log.assert_called_once_with( '"file": in paths "%s" exists: "False" mode match: not checked' % mock_env.return_value )
def has_rpm(self): """ Check if rpm binary was found in root_dir """ rpm_search_env = {'PATH': os.sep.join([self.root_dir, 'usr', 'bin'])} rpm_bin = Path.which('rpm', custom_env=rpm_search_env, access_mode=os.X_OK) if not rpm_bin: return False return True
def has_rpm(self): """ Check if rpmdb binary was found in root_dir to indicate that the rpm system is present. """ rpm_bin = Path.which('rpmdb', root_dir=self.root_dir, access_mode=os.X_OK) if not rpm_bin: return False return True
def test_which_not_found_for_mode_log( self, mock_log, mock_exists, mock_env, mock_access ): mock_env.return_value = '/usr/local/bin:/usr/bin:/bin' mock_exists.return_value = True mock_access.return_value = False assert Path.which('file', access_mode=os.X_OK) is None mock_log.assert_called_once_with( '"file": in paths "%s" exists: "True" mode match: "False"' % mock_env.return_value )
def has_rpm(self): """ Check if rpmdb binary was found in root_dir to indicate that the rpm system is present. """ rpm_search_env = {'PATH': os.sep.join([self.root_dir, 'usr', 'bin'])} rpm_bin = Path.which('rpmdb', custom_env=rpm_search_env, access_mode=os.X_OK) if not rpm_bin: return False return True
def check_container_tool_chain_installed(self) -> None: """ When creating container images the specific tools are used in order to import and export OCI or Docker compatible images. This check searches for those tools to be installed in the build system and fails if it can't find them """ message_tool_not_found = dedent('''\n Required tool {name} not found in caller environment Creation of OCI or Docker images requires the tools {name} and skopeo to be installed on the build system. For SUSE based systems you can find the tools at: http://download.opensuse.org/repositories/Virtualization:/containers ''') message_version_unsupported = dedent('''\n {name} tool found with unknown version ''') message_unknown_tool = dedent('''\n Unknown tool: {0}. Please configure KIWI with an appropriate value (umoci or buildah). Consider this runtime configuration file syntax (/etc/kiwi.yml): oci: - archive_tool: umoci | buildah ''') expected_version = (0, 1, 0) if self.xml_state.get_build_type_name() in ['docker', 'oci']: runtime_config = RuntimeConfig() tool_name = runtime_config.get_oci_archive_tool() if tool_name == 'buildah': oci_tools = ['buildah', 'skopeo'] elif tool_name == 'umoci': oci_tools = ['umoci', 'skopeo'] else: raise KiwiRuntimeError(message_unknown_tool.format(tool_name)) for tool in oci_tools: if not Path.which(filename=tool, access_mode=os.X_OK): raise KiwiRuntimeError( message_tool_not_found.format(name=tool) ) elif not CommandCapabilities.check_version( tool, expected_version, raise_on_error=False ): raise KiwiRuntimeError( message_version_unsupported.format(name=tool) ) self._check_multitag_support()
def _get_tool_name( self, root_path, lookup_list, fallback_on_not_found=True ): for tool in lookup_list: if Path.which(filename=tool, root_dir=root_path): return tool if fallback_on_not_found: # no tool from the list was found, we intentionally don't # raise here but return the default tool name and raise # an exception at invocation time in order to log the # expected call and its arguments return lookup_list[0]
def init_iso_creation_parameters(self, custom_args=None): """ Create a set of standard parameters :param list custom_args: custom ISO meta data """ if custom_args: if 'mbr_id' in custom_args: self.iso_parameters += [ '-application_id', custom_args['mbr_id'] ] if 'publisher' in custom_args: self.iso_parameters += [ '-publisher', custom_args['publisher'] ] if 'preparer' in custom_args: self.iso_parameters += [ '-preparer_id', custom_args['preparer'] ] if 'volume_id' in custom_args: self.iso_parameters += [ '-volid', custom_args['volume_id'] ] catalog_file = self.boot_path + '/boot.catalog' self.iso_parameters += [ '-joliet', 'on', '-padding', '0' ] loader_file = self.boot_path + '/loader/isolinux.bin' syslinux_lookup_paths = [ '/usr/share/syslinux', '/usr/lib/syslinux/modules/bios', '/usr/lib/ISOLINUX' ] mbr_file = Path.which('isohdpfx.bin', syslinux_lookup_paths) if not mbr_file: raise KiwiIsoToolError( 'isohdpfx.bin not found in {0}'.format(syslinux_lookup_paths) ) self.iso_loaders += [ '-boot_image', 'any', 'partition_offset=16', '-boot_image', 'isolinux', 'bin_path={0}'.format(loader_file), '-boot_image', 'isolinux', 'system_area={0}'.format(mbr_file), '-boot_image', 'isolinux', 'partition_table=on', '-boot_image', 'any', 'cat_path={0}'.format(catalog_file), '-boot_image', 'any', 'cat_hidden=on', '-boot_image', 'any', 'boot_info_table=on', '-boot_image', 'any', 'platform_id=0x00', '-boot_image', 'any', 'emul_type=no_emulation', '-boot_image', 'any', 'load_size=2048' ]
def get_tool_name(self): """ Lookup xorriso in search path :raises KiwiIsoToolError: if xorriso tool is not found :return: xorriso tool path :rtype: str """ xorriso = Path.which('xorriso') if xorriso: return xorriso raise KiwiIsoToolError('xorriso tool not found')
def init_iso_creation_parameters(self, custom_args=None): """ Create a set of standard parameters :param list custom_args: custom ISO meta data """ if custom_args: if 'mbr_id' in custom_args: self.iso_parameters += [ '-application_id', custom_args['mbr_id'] ] if 'publisher' in custom_args: self.iso_parameters += [ '-publisher', custom_args['publisher'] ] if 'preparer' in custom_args: self.iso_parameters += [ '-preparer_id', custom_args['preparer'] ] if 'volume_id' in custom_args: self.iso_parameters += [ '-volid', custom_args['volume_id'] ] catalog_file = self.boot_path + '/boot.catalog' self.iso_parameters += [ '-joliet', 'on', '-padding', '0' ] loader_file = self.boot_path + '/loader/isolinux.bin' syslinux_lookup_paths = [ '/usr/share/syslinux', '/usr/lib/syslinux/modules/bios' ] mbr_file = Path.which('isohdpfx.bin', syslinux_lookup_paths) if not mbr_file: raise KiwiIsoToolError( 'isohdpfx.bin not found in {0}'.format(syslinux_lookup_paths) ) self.iso_loaders += [ '-boot_image', 'any', 'partition_offset=16', '-boot_image', 'isolinux', 'bin_path={0}'.format(loader_file), '-boot_image', 'isolinux', 'system_area={0}'.format(mbr_file), '-boot_image', 'isolinux', 'partition_table=on', '-boot_image', 'any', 'cat_path={0}'.format(catalog_file), '-boot_image', 'any', 'cat_hidden=on', '-boot_image', 'any', 'boot_info_table=on', '-boot_image', 'any', 'platform_id=0x00', '-boot_image', 'any', 'emul_type=no_emulation', '-boot_image', 'any', 'load_size=2048' ]
def _get_tool_name( self, root_path, lookup_list, fallback_on_not_found=True ): chroot_env = {'PATH': os.sep.join([root_path, 'usr', 'sbin'])} for tool in lookup_list: if Path.which(filename=tool, custom_env=chroot_env): return tool if fallback_on_not_found: # no tool from the list was found, we intentionally don't # raise here but return the default tool name and raise # an exception at invocation time in order to log the # expected call and its arguments return lookup_list[0]
def _find_iso_creation_tool(self): """ There are tools by J.Schilling and tools from the community Depending on what is installed a decision needs to be made """ iso_creation_tools = ['mkisofs', 'genisoimage'] for tool in iso_creation_tools: tool_found = Path.which(tool) if tool_found: return tool_found raise KiwiIsoToolError( 'No iso creation tool found, searched for: %s' % iso_creation_tools )
def setup_plymouth_splash(self): """ Setup the KIWI configured splash theme as default The method uses the plymouth-set-default-theme tool to setup the theme for the plymouth splash system. Only in case the tool could be found in the image root, it is assumed plymouth splash is in use and the tool is called in a chroot operation """ theme_setup = 'plymouth-set-default-theme' if Path.which(filename=theme_setup, root_dir=self.root_dir): for preferences in self.xml_state.get_preferences_sections(): splash_section_content = preferences.get_bootsplash_theme() if splash_section_content: splash_theme = splash_section_content[0] Command.run( ['chroot', self.root_dir, theme_setup, splash_theme])
def check_mediacheck_installed(self) -> None: """ If the image description enables the mediacheck attribute the required tools to run this check must be installed on the image build host """ message_tool_not_found = dedent('''\n Required tool {name} not found in caller environment The attribute 'mediacheck' is set to 'true' which requires the above tool to be installed on the build system ''') if self.xml_state.build_type.get_mediacheck() is True: tool = 'tagmedia' if not Path.which(filename=tool, access_mode=os.X_OK): raise KiwiRuntimeError( message_tool_not_found.format(name=tool))
def _create_efi_image(self, uuid=None, mbrid=None, lookup_path=None): early_boot_script = self.efi_boot_path + '/earlyboot.cfg' if uuid: self._create_early_boot_script_for_uuid_search( early_boot_script, uuid) else: self._create_early_boot_script_for_mbrid_search( early_boot_script, mbrid) for grub_mkimage_tool in ['grub2-mkimage', 'grub-mkimage']: if Path.which(grub_mkimage_tool): break Command.run([ grub_mkimage_tool, '-O', Defaults.get_efi_module_directory_name(self.arch), '-o', self._get_efi_image_name(), '-c', early_boot_script, '-p', self.get_boot_path() + '/' + self.boot_directory_name, '-d', self._get_efi_modules_path(lookup_path) ] + Defaults.get_grub_efi_modules(multiboot=self.xen_guest))
def create_image_format(self): """ Create ova disk format using ovftool from https://www.vmware.com/support/developer/ovf """ # Check for required ovftool ovftool = Path.which(filename='ovftool', access_mode=os.X_OK) if not ovftool: tool_not_found_message = dedent('''\n Required tool {0} not found in PATH on the build host Building OVA images requires VMware's {0} tool which can be installed from the following location https://www.vmware.com/support/developer/ovf ''') raise KiwiCommandNotFound( tool_not_found_message.format(ovftool) ) # Create the vmdk disk image and vmx config self.vmdk.create_image_format() # Convert to ova using ovftool vmx = self.get_target_file_path_for_format('vmx') ova = self.get_target_file_path_for_format('ova') try: os.unlink(ova) except OSError: pass ovftool_options = [] if CommandCapabilities.has_option_in_help( ovftool, '--shaAlgorithm', raise_on_error=False ): ovftool_options.append('--shaAlgorithm=SHA1') Command.run( [ovftool] + ovftool_options + [vmx, ova] ) # ovftool ignores the umask and creates files with 0600 # apply file permission bits set in the vmx file to the # ova file st = os.stat(vmx) os.chmod(ova, stat.S_IMODE(st.st_mode))
def create_image_format(self): """ Create ova disk format using ovftool from https://www.vmware.com/support/developer/ovf """ # Check for required ovftool ovftool = Path.which(filename='ovftool', access_mode=os.X_OK) if not ovftool: tool_not_found_message = dedent('''\n Required tool {0} not found in PATH on the build host Building OVA images requires VMware's {0} tool which can be installed from the following location https://www.vmware.com/support/developer/ovf ''') raise KiwiCommandNotFound( tool_not_found_message.format(ovftool) ) # Create the vmdk disk image and vmx config super(DiskFormatOva, self).create_image_format() # Convert to ova using ovftool vmx = self.get_target_file_path_for_format('vmx') ova = self.get_target_file_path_for_format('ova') try: os.unlink(ova) except OSError: pass ovftool_options = [] if CommandCapabilities.has_option_in_help( ovftool, '--shaAlgorithm', raise_on_error=False ): ovftool_options.append('--shaAlgorithm=SHA1') Command.run( [ovftool] + ovftool_options + [vmx, ova] ) # ovftool ignores the umask and creates files with 0600 # apply file permission bits set in the vmx file to the # ova file st = os.stat(vmx) os.chmod(ova, stat.S_IMODE(st.st_mode))
def _get_isoinfo_tool(self): """ There are tools by J.Schilling and tools from the community This method searches in all paths which could provide an isoinfo tool. The first match makes the decision :raises KiwiIsoToolError: if no isoinfo tool found :return: the isoinfo tool to use :rtype: str """ alternative_lookup_paths = ['/usr/lib/genisoimage'] isoinfo = Path.which('isoinfo', alternative_lookup_paths) if isoinfo: return isoinfo raise KiwiIsoToolError( 'No isoinfo tool found, searched in PATH: %s and %s' % (os.environ.get('PATH'), alternative_lookup_paths))
def _get_yum_binary_name(self, root=None): """ Identify whether yum is 'yum' or 'yum-deprecated' :param string root: lookup binary name below this root directory :return: name of yum command """ yum_binary = 'yum' yum_search_env = { 'PATH': os.sep.join([root, 'usr', 'bin']) } if root else None if Path.which( filename='yum-deprecated', custom_env=yum_search_env, access_mode=os.X_OK ): yum_binary = 'yum-deprecated' return yum_binary
def _get_isoinfo_tool(self): """ There are tools by J.Schilling and tools from the community This method searches in all paths which could provide an isoinfo tool. The first match makes the decision :raises KiwiIsoToolError: if no isoinfo tool found :return: the isoinfo tool to use :rtype: str """ alternative_lookup_paths = ['/usr/lib/genisoimage'] isoinfo = Path.which('isoinfo', alternative_lookup_paths) if isoinfo: return isoinfo raise KiwiIsoToolError( 'No isoinfo tool found, searched in PATH: %s and %s' % (os.environ.get('PATH'), alternative_lookup_paths) )
def invoke_kiwicompat(self, compat_args): """ Execute kiwicompat with provided legacy KIWI command line arguments Example: .. code:: python invoke_kiwicompat( '--build', 'description', '--type', 'vmx', '-d', 'destination' ) :param list compat_args: legacy kiwi command arguments """ kiwicompat = Path.which('kiwicompat', access_mode=os.X_OK) try: os.execvp(kiwicompat, ['kiwicompat'] + compat_args) except Exception as e: raise KiwiCompatError('%s: %s' % (type(e).__name__, format(e)))
def _get_yum_binary_name(self, root=None): """ Identify whether yum is 'yum' or 'yum-deprecated' :param str root: lookup binary name below this root directory :return: name of yum command :rtype: str """ yum_binary = 'yum' yum_search_env = { 'PATH': os.sep.join([root, 'usr', 'bin']) } if root else None if Path.which(filename='yum-deprecated', custom_env=yum_search_env, access_mode=os.X_OK): yum_binary = 'yum-deprecated' return yum_binary
def setup_plymouth_splash(self): """ Setup the KIWI configured splash theme as default The method uses the plymouth-set-default-theme tool to setup the theme for the plymouth splash system. Only in case the tool could be found in the image root, it is assumed plymouth splash is in use and the tool is called in a chroot operation """ chroot_env = { 'PATH': os.sep.join([self.root_dir, 'usr', 'sbin']) } theme_setup = 'plymouth-set-default-theme' if Path.which(filename=theme_setup, custom_env=chroot_env): for preferences in self.xml_state.get_preferences_sections(): splash_section_content = preferences.get_bootsplash_theme() if splash_section_content: splash_theme = splash_section_content[0] Command.run( ['chroot', self.root_dir, theme_setup, splash_theme] )
def get_tool_name(self): """ There are tools by J.Schilling and tools from the community Depending on what is installed a decision needs to be made. mkisofs is preferred over genisoimage :raises KiwiIsoToolError: if no iso creation tool is found :return: tool name :rtype: str """ iso_creation_tools = ['mkisofs', 'genisoimage'] for tool in iso_creation_tools: tool_found = Path.which(tool) if tool_found: return tool_found raise KiwiIsoToolError( 'No iso creation tool found, searched for: %s'.format( iso_creation_tools ) )
def _create_efi_image(self, uuid=None, mbrid=None, lookup_path=None): early_boot_script = self.efi_boot_path + '/earlyboot.cfg' if uuid: self._create_early_boot_script_for_uuid_search( early_boot_script, uuid ) else: self._create_early_boot_script_for_mbrid_search( early_boot_script, mbrid ) for grub_mkimage_tool in ['grub2-mkimage', 'grub-mkimage']: if Path.which(grub_mkimage_tool): break Command.run( [ grub_mkimage_tool, '-O', Defaults.get_efi_module_directory_name(self.arch), '-o', self._get_efi_image_name(), '-c', early_boot_script, '-p', self.get_boot_path() + '/' + self.boot_directory_name, '-d', self._get_efi_modules_path(lookup_path) ] + Defaults.get_grub_efi_modules(multiboot=self.xen_guest) )
def test_which(self, mock_exists, mock_env, mock_access): mock_env.return_value = '/usr/local/bin:/usr/bin:/bin' mock_exists.return_value = True assert Path.which('some-file') == '/usr/local/bin/some-file' mock_exists.return_value = False assert Path.which('some-file') is None mock_env.return_value = None mock_exists.return_value = True assert Path.which('some-file', ['alternative']) == \ 'alternative/some-file' mock_access.return_value = False mock_env.return_value = '/usr/local/bin:/usr/bin:/bin' assert Path.which('some-file', access_mode=os.X_OK) is None mock_access.return_value = True assert Path.which('some-file', access_mode=os.X_OK) == \ '/usr/local/bin/some-file' assert Path.which('some-file', custom_env={'PATH': 'custom_path'}) == \ 'custom_path/some-file'
def __init__(self, data, style='standard'): self.data = data self.style = style self.color_json = Path.which('pjson')
def process(self): """ Create result bundle from the image build results in the specified target directory. Each result image will contain the specified bundle identifier as part of its filename. Uncompressed image files will also become xz compressed and a sha sum will be created from every result image """ self.manual = Help() if self._help(): return # load serialized result object from target directory result_directory = os.path.abspath(self.command_args['--target-dir']) bundle_directory = os.path.abspath(self.command_args['--bundle-dir']) if result_directory == bundle_directory: raise KiwiBundleError( 'Bundle directory must be different from target directory' ) log.info( 'Bundle build results from %s', result_directory ) result = Result.load( result_directory + '/kiwi.result' ) image_version = result.xml_state.get_image_version() ordered_results = OrderedDict(sorted(result.get_results().items())) # hard link bundle files, compress and build checksum if not os.path.exists(bundle_directory): Path.create(bundle_directory) for result_file in list(ordered_results.values()): if result_file.use_for_bundle: bundle_file_basename = os.path.basename(result_file.filename) # The bundle id is only taken into account for image results # which contains the image version in its nane bundle_file_basename = bundle_file_basename.replace( image_version, image_version + '-' + self.command_args['--id'] ) log.info('Creating %s', bundle_file_basename) bundle_file = ''.join( [bundle_directory, '/', bundle_file_basename] ) checksum_file = ''.join( [bundle_directory, '/', bundle_file_basename, '.sha256'] ) Command.run( [ 'cp', result_file.filename, bundle_file ] ) if result_file.compress: log.info('--> XZ compressing') compress = Compress(bundle_file) compress.xz(self.runtime_config.get_xz_options()) bundle_file = compress.compressed_filename checksum_file = compress.compressed_filename + '.sha256' if self.command_args['--zsync-source']: zsyncmake = Path.which('zsyncmake', access_mode=os.X_OK) if zsyncmake: log.info('--> Creating zsync control file') Command.run( [ zsyncmake, '-e', '-u', os.sep.join( [ self.command_args['--zsync-source'], os.path.basename(bundle_file) ] ), '-o', bundle_file + '.zsync', bundle_file ] ) else: log.warning( '--> zsyncmake missing, zsync setup skipped' ) if result_file.shasum: log.info('--> Creating SHA 256 sum') checksum = Checksum(bundle_file) with open(checksum_file, 'w') as shasum: shasum.write(checksum.sha256())