def test_mkfs_with_label(self, execute_mock): utils.mkfs("ext4", "/my/block/dev", "ext4-vol") utils.mkfs("msdos", "/my/msdos/block/dev", "msdos-vol") utils.mkfs("swap", "/my/swap/block/dev", "swap-vol") expected = [ mock.call( "mkfs", "-t", "ext4", "-F", "-L", "ext4-vol", "/my/block/dev", run_as_root=True, use_standard_locale=True, ), mock.call( "mkfs", "-t", "msdos", "-n", "msdos-vol", "/my/msdos/block/dev", run_as_root=True, use_standard_locale=True, ), mock.call("mkswap", "-L", "swap-vol", "/my/swap/block/dev", run_as_root=True, use_standard_locale=True), ] self.assertEqual(expected, execute_mock.call_args_list)
def test_mkfs_with_label(self, execute_mock): utils.mkfs('ext4', '/my/block/dev', 'ext4-vol') utils.mkfs('msdos', '/my/msdos/block/dev', 'msdos-vol') utils.mkfs('swap', '/my/swap/block/dev', 'swap-vol') expected = [mock.call('mkfs', '-t', 'ext4', '-F', '-L', 'ext4-vol', '/my/block/dev', run_as_root=True, use_standard_locale=True), mock.call('mkfs', '-t', 'msdos', '-n', 'msdos-vol', '/my/msdos/block/dev', run_as_root=True, use_standard_locale=True), mock.call('mkswap', '-L', 'swap-vol', '/my/swap/block/dev', run_as_root=True, use_standard_locale=True)] self.assertEqual(expected, execute_mock.call_args_list)
def mkfs(fs, dev, label=None): """Execute mkfs on a device.""" utils.mkfs(fs, dev, label)
def create_vfat_image(output_file, files_info=None, parameters=None, parameters_file='parameters.txt', fs_size_kib=100): """Creates the fat fs image on the desired file. This method copies the given files to a root directory (optional), writes the parameters specified to the parameters file within the root directory (optional), and then creates a vfat image of the root directory. :param output_file: The path to the file where the fat fs image needs to be created. :param files_info: A dict containing absolute path of file to be copied -> relative path within the vfat image. For example, { '/absolute/path/to/file' -> 'relative/path/within/root' ... } :param parameters: A dict containing key-value pairs of parameters. :param parameters_file: The filename for the parameters file. :param fs_size_kib: size of the vfat filesystem in KiB. :raises: ImageCreationFailed, if image creation failed while doing any of filesystem manipulation activities like creating dirs, mounting, creating filesystem, copying files, etc. """ try: ironic_utils.dd('/dev/zero', output_file, 'count=1', "bs=%dKiB" % fs_size_kib) except processutils.ProcessExecutionError as e: raise exception.ImageCreationFailed(image_type='vfat', error=e) with utils.tempdir() as tmpdir: try: # The label helps ramdisks to find the partition containing # the parameters (by using /dev/disk/by-label/ir-vfd-dev). # NOTE: FAT filesystem label can be up to 11 characters long. ironic_utils.mkfs('vfat', output_file, label="ir-vfd-dev") utils.mount(output_file, tmpdir, '-o', 'umask=0') except processutils.ProcessExecutionError as e: raise exception.ImageCreationFailed(image_type='vfat', error=e) try: if files_info: _create_root_fs(tmpdir, files_info) if parameters: parameters_file = os.path.join(tmpdir, parameters_file) params_list = ['%(key)s=%(val)s' % {'key': k, 'val': v} for k, v in parameters.items()] file_contents = '\n'.join(params_list) utils.write_to_file(parameters_file, file_contents) except Exception as e: LOG.exception(_LE("vfat image creation failed. Error: %s"), e) raise exception.ImageCreationFailed(image_type='vfat', error=e) finally: try: utils.umount(tmpdir) except processutils.ProcessExecutionError as e: raise exception.ImageCreationFailed(image_type='vfat', error=e)
def work_on_disk(dev, root_mb, swap_mb, ephemeral_mb, ephemeral_format, image_path, node_uuid, preserve_ephemeral=False, configdrive=None, boot_option="netboot", boot_mode="bios", tempdir=None, disk_label=None): """Create partitions and copy an image to the root partition. :param dev: Path for the device to work on. :param root_mb: Size of the root partition in megabytes. :param swap_mb: Size of the swap partition in megabytes. :param ephemeral_mb: Size of the ephemeral partition in megabytes. If 0, no ephemeral partition will be created. :param ephemeral_format: The type of file system to format the ephemeral partition. :param image_path: Path for the instance's disk image. :param node_uuid: node's uuid. Used for logging. :param preserve_ephemeral: If True, no filesystem is written to the ephemeral block device, preserving whatever content it had (if the partition table has not changed). :param configdrive: Optional. Base64 encoded Gzipped configdrive content or configdrive HTTP URL. :param boot_option: Can be "local" or "netboot". "netboot" by default. :param boot_mode: Can be "bios" or "uefi". "bios" by default. :param tempdir: A temporary directory :param disk_label: The disk label to be used when creating the partition table. Valid values are: "msdos", "gpt" or None; If None Ironic will figure it out according to the boot_mode parameter. :returns: a dictionary containing the following keys: 'root uuid': UUID of root partition 'efi system partition uuid': UUID of the uefi system partition (if boot mode is uefi). NOTE: If key exists but value is None, it means partition doesn't exist. """ # the only way for preserve_ephemeral to be set to true is if we are # rebuilding an instance with --preserve_ephemeral. commit = not preserve_ephemeral # now if we are committing the changes to disk clean first. if commit: destroy_disk_metadata(dev, node_uuid) try: # If requested, get the configdrive file and determine the size # of the configdrive partition configdrive_mb = 0 configdrive_file = None if configdrive: configdrive_mb, configdrive_file = _get_configdrive( configdrive, node_uuid, tempdir=tempdir) part_dict = make_partitions(dev, root_mb, swap_mb, ephemeral_mb, configdrive_mb, node_uuid, commit=commit, boot_option=boot_option, boot_mode=boot_mode, disk_label=disk_label) LOG.info( "Successfully completed the disk device" " %(dev)s partitioning for node %(node)s", { 'dev': dev, "node": node_uuid }) ephemeral_part = part_dict.get('ephemeral') swap_part = part_dict.get('swap') configdrive_part = part_dict.get('configdrive') root_part = part_dict.get('root') if not is_block_device(root_part): raise exception.InstanceDeployFailure( _("Root device '%s' not found") % root_part) for part in ('swap', 'ephemeral', 'configdrive', 'efi system partition'): part_device = part_dict.get(part) LOG.debug( "Checking for %(part)s device (%(dev)s) on node " "%(node)s.", { 'part': part, 'dev': part_device, 'node': node_uuid }) if part_device and not is_block_device(part_device): raise exception.InstanceDeployFailure( _("'%(partition)s' device '%(part_device)s' not found") % { 'partition': part, 'part_device': part_device }) # If it's a uefi localboot, then we have created the efi system # partition. Create a fat filesystem on it. if boot_mode == "uefi" and boot_option == "local": efi_system_part = part_dict.get('efi system partition') utils.mkfs(fs='vfat', path=efi_system_part, label='efi-part') if configdrive_part: # Copy the configdrive content to the configdrive partition dd(configdrive_file, configdrive_part) LOG.info( "Configdrive for node %(node)s successfully copied " "onto partition %(partition)s", { 'node': node_uuid, 'partition': configdrive_part }) finally: # If the configdrive was requested make sure we delete the file # after copying the content to the partition if configdrive_file: utils.unlink_without_raise(configdrive_file) populate_image(image_path, root_part) LOG.info("Image for %(node)s successfully populated", {'node': node_uuid}) if swap_part: utils.mkfs(fs='swap', path=swap_part, label='swap1') LOG.info( "Swap partition %(swap)s successfully formatted " "for node %(node)s", { 'swap': swap_part, 'node': node_uuid }) if ephemeral_part and not preserve_ephemeral: utils.mkfs(fs=ephemeral_format, path=ephemeral_part, label="ephemeral0") LOG.info( "Ephemeral partition %(ephemeral)s successfully " "formatted for node %(node)s", { 'ephemeral': ephemeral_part, 'node': node_uuid }) uuids_to_return = { 'root uuid': root_part, 'efi system partition uuid': part_dict.get('efi system partition') } try: for part, part_dev in uuids_to_return.items(): if part_dev: uuids_to_return[part] = block_uuid(part_dev) except processutils.ProcessExecutionError: with excutils.save_and_reraise_exception(): LOG.error("Failed to detect %s", part) return uuids_to_return
def work_on_disk(dev, root_mb, swap_mb, ephemeral_mb, ephemeral_format, image_path, node_uuid, preserve_ephemeral=False, configdrive=None, boot_option="netboot", boot_mode="bios", tempdir=None, disk_label=None): """Create partitions and copy an image to the root partition. :param dev: Path for the device to work on. :param root_mb: Size of the root partition in megabytes. :param swap_mb: Size of the swap partition in megabytes. :param ephemeral_mb: Size of the ephemeral partition in megabytes. If 0, no ephemeral partition will be created. :param ephemeral_format: The type of file system to format the ephemeral partition. :param image_path: Path for the instance's disk image. :param node_uuid: node's uuid. Used for logging. :param preserve_ephemeral: If True, no filesystem is written to the ephemeral block device, preserving whatever content it had (if the partition table has not changed). :param configdrive: Optional. Base64 encoded Gzipped configdrive content or configdrive HTTP URL. :param boot_option: Can be "local" or "netboot". "netboot" by default. :param boot_mode: Can be "bios" or "uefi". "bios" by default. :param tempdir: A temporary directory :param disk_label: The disk label to be used when creating the partition table. Valid values are: "msdos", "gpt" or None; If None Ironic will figure it out according to the boot_mode parameter. :returns: a dictionary containing the following keys: 'root uuid': UUID of root partition 'efi system partition uuid': UUID of the uefi system partition (if boot mode is uefi). NOTE: If key exists but value is None, it means partition doesn't exist. """ # the only way for preserve_ephemeral to be set to true is if we are # rebuilding an instance with --preserve_ephemeral. commit = not preserve_ephemeral # now if we are committing the changes to disk clean first. if commit: destroy_disk_metadata(dev, node_uuid) try: # If requested, get the configdrive file and determine the size # of the configdrive partition configdrive_mb = 0 configdrive_file = None if configdrive: configdrive_mb, configdrive_file = _get_configdrive( configdrive, node_uuid, tempdir=tempdir) part_dict = make_partitions(dev, root_mb, swap_mb, ephemeral_mb, configdrive_mb, node_uuid, commit=commit, boot_option=boot_option, boot_mode=boot_mode, disk_label=disk_label) LOG.info(_LI("Successfully completed the disk device" " %(dev)s partitioning for node %(node)s"), {'dev': dev, "node": node_uuid}) ephemeral_part = part_dict.get('ephemeral') swap_part = part_dict.get('swap') configdrive_part = part_dict.get('configdrive') root_part = part_dict.get('root') if not is_block_device(root_part): raise exception.InstanceDeployFailure( _("Root device '%s' not found") % root_part) for part in ('swap', 'ephemeral', 'configdrive', 'efi system partition'): part_device = part_dict.get(part) LOG.debug("Checking for %(part)s device (%(dev)s) on node " "%(node)s.", {'part': part, 'dev': part_device, 'node': node_uuid}) if part_device and not is_block_device(part_device): raise exception.InstanceDeployFailure( _("'%(partition)s' device '%(part_device)s' not found") % {'partition': part, 'part_device': part_device}) # If it's a uefi localboot, then we have created the efi system # partition. Create a fat filesystem on it. if boot_mode == "uefi" and boot_option == "local": efi_system_part = part_dict.get('efi system partition') utils.mkfs(fs='vfat', path=efi_system_part, label='efi-part') if configdrive_part: # Copy the configdrive content to the configdrive partition dd(configdrive_file, configdrive_part) LOG.info(_LI("Configdrive for node %(node)s successfully copied " "onto partition %(partition)s"), {'node': node_uuid, 'partition': configdrive_part}) finally: # If the configdrive was requested make sure we delete the file # after copying the content to the partition if configdrive_file: utils.unlink_without_raise(configdrive_file) populate_image(image_path, root_part) LOG.info(_LI("Image for %(node)s successfully populated"), {'node': node_uuid}) if swap_part: utils.mkfs(fs='swap', path=swap_part, label='swap1') LOG.info(_LI("Swap partition %(swap)s successfully formatted " "for node %(node)s"), {'swap': swap_part, 'node': node_uuid}) if ephemeral_part and not preserve_ephemeral: utils.mkfs(fs=ephemeral_format, path=ephemeral_part, label="ephemeral0") LOG.info(_LI("Ephemeral partition %(ephemeral)s successfully " "formatted for node %(node)s"), {'ephemeral': ephemeral_part, 'node': node_uuid}) uuids_to_return = { 'root uuid': root_part, 'efi system partition uuid': part_dict.get('efi system partition') } try: for part, part_dev in uuids_to_return.items(): if part_dev: uuids_to_return[part] = block_uuid(part_dev) except processutils.ProcessExecutionError: with excutils.save_and_reraise_exception(): LOG.error(_LE("Failed to detect %s"), part) return uuids_to_return
def create_vfat_image(output_file, files_info=None, parameters=None, parameters_file='parameters.txt', fs_size_kib=100): """Creates the fat fs image on the desired file. This method copies the given files to a root directory (optional), writes the parameters specified to the parameters file within the root directory (optional), and then creates a vfat image of the root directory. :param output_file: The path to the file where the fat fs image needs to be created. :param files_info: A dict containing absolute path of file to be copied -> relative path within the vfat image. For example:: { '/absolute/path/to/file' -> 'relative/path/within/root' ... } :param parameters: A dict containing key-value pairs of parameters. :param parameters_file: The filename for the parameters file. :param fs_size_kib: size of the vfat filesystem in KiB. :raises: ImageCreationFailed, if image creation failed while doing any of filesystem manipulation activities like creating dirs, mounting, creating filesystem, copying files, etc. """ try: ironic_utils.dd('/dev/zero', output_file, 'count=1', "bs=%dKiB" % fs_size_kib) except processutils.ProcessExecutionError as e: raise exception.ImageCreationFailed(image_type='vfat', error=e) with utils.tempdir() as tmpdir: try: # The label helps ramdisks to find the partition containing # the parameters (by using /dev/disk/by-label/ir-vfd-dev). # NOTE: FAT filesystem label can be up to 11 characters long. ironic_utils.mkfs('vfat', output_file, label="ir-vfd-dev") utils.mount(output_file, tmpdir, '-o', 'umask=0') except processutils.ProcessExecutionError as e: raise exception.ImageCreationFailed(image_type='vfat', error=e) try: if files_info: _create_root_fs(tmpdir, files_info) if parameters: parameters_file = os.path.join(tmpdir, parameters_file) params_list = ['%(key)s=%(val)s' % {'key': k, 'val': v} for k, v in parameters.items()] file_contents = '\n'.join(params_list) utils.write_to_file(parameters_file, file_contents) except Exception as e: LOG.exception("vfat image creation failed. Error: %s", e) raise exception.ImageCreationFailed(image_type='vfat', error=e) finally: try: utils.umount(tmpdir) except processutils.ProcessExecutionError as e: raise exception.ImageCreationFailed(image_type='vfat', error=e)