def check_image_size(task): """Check if the requested image is larger than the root partition size. Does nothing for whole-disk images. :param task: a TaskManager instance containing the node to act on. :raises: InstanceDeployFailure if size of the image is greater than root partition. """ if task.node.driver_internal_info['is_whole_disk_image']: # The root partition is already created and populated, no use # validating its size return i_info = deploy_utils.parse_instance_info(task.node) image_path = deploy_utils._get_image_file_path(task.node.uuid) image_mb = disk_utils.get_image_mb(image_path) root_mb = 1024 * int(i_info['root_gb']) if image_mb > root_mb: msg = (_('Root partition is too small for requested image. Image ' 'virtual size: %(image_mb)d MB, Root size: %(root_mb)d MB') % { 'image_mb': image_mb, 'root_mb': root_mb }) raise exception.InstanceDeployFailure(msg)
def _write_partition_image(image, image_info, device): """Call disk_util to create partition and write the partition image.""" node_uuid = image_info.get('node_uuid') preserve_ep = image_info['preserve_ephemeral'] configdrive = image_info['configdrive'] boot_option = image_info.get('boot_option', 'netboot') boot_mode = image_info.get('deploy_boot_mode', 'bios') disk_label = image_info.get('disk_label', 'msdos') image_mb = disk_utils.get_image_mb(image) root_mb = image_info['root_mb'] if image_mb > int(root_mb): msg = ('Root partition is too small for requested image. Image ' 'virtual size: {0} MB, Root size: {1} MB').format( image_mb, root_mb) raise errors.InvalidCommandParamsError(msg) try: return disk_utils.work_on_disk(device, root_mb, image_info['swap_mb'], image_info['ephemeral_mb'], image_info['ephemeral_format'], image, node_uuid, preserve_ephemeral=preserve_ep, configdrive=configdrive, boot_option=boot_option, boot_mode=boot_mode, disk_label=disk_label) except processutils.ProcessExecutionError as e: raise errors.ImageWriteError(device, e.exit_code, e.stdout, e.stderr)
def deploy_partition_image( address, port, iqn, lun, image_path, root_mb, swap_mb, ephemeral_mb, ephemeral_format, node_uuid, preserve_ephemeral=False, configdrive=None, boot_option=None, boot_mode="bios", disk_label=None, cpu_arch=""): """All-in-one function to deploy a partition image to a node. :param address: The iSCSI IP address. :param port: The iSCSI port number. :param iqn: The iSCSI qualified name. :param lun: The iSCSI logical unit number. :param image_path: Path for the instance's disk image. :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 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 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. :param cpu_arch: Architecture of the node being deployed to. :raises: InstanceDeployFailure if image virtual size is bigger than root partition size. :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. """ boot_option = boot_option or deploy_utils.get_default_boot_option() image_mb = disk_utils.get_image_mb(image_path) if image_mb > root_mb: msg = (_('Root partition is too small for requested image. Image ' 'virtual size: %(image_mb)d MB, Root size: %(root_mb)d MB') % {'image_mb': image_mb, 'root_mb': root_mb}) raise exception.InstanceDeployFailure(msg) with _iscsi_setup_and_handle_errors(address, port, iqn, lun) as dev: uuid_dict_returned = disk_utils.work_on_disk( dev, root_mb, swap_mb, ephemeral_mb, ephemeral_format, image_path, node_uuid, preserve_ephemeral=preserve_ephemeral, configdrive=configdrive, boot_option=boot_option, boot_mode=boot_mode, disk_label=disk_label, cpu_arch=cpu_arch) return uuid_dict_returned
def deploy_partition_image( address, port, iqn, lun, image_path, root_mb, swap_mb, ephemeral_mb, ephemeral_format, node_uuid, preserve_ephemeral=False, configdrive=None, boot_option=None, boot_mode="bios", disk_label=None): """All-in-one function to deploy a partition image to a node. :param address: The iSCSI IP address. :param port: The iSCSI port number. :param iqn: The iSCSI qualified name. :param lun: The iSCSI logical unit number. :param image_path: Path for the instance's disk image. :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 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 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. :raises: InstanceDeployFailure if image virtual size is bigger than root partition size. :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. """ boot_option = boot_option or get_default_boot_option() image_mb = disk_utils.get_image_mb(image_path) if image_mb > root_mb: msg = (_('Root partition is too small for requested image. Image ' 'virtual size: %(image_mb)d MB, Root size: %(root_mb)d MB') % {'image_mb': image_mb, 'root_mb': root_mb}) raise exception.InstanceDeployFailure(msg) with _iscsi_setup_and_handle_errors(address, port, iqn, lun) as dev: uuid_dict_returned = disk_utils.work_on_disk( dev, root_mb, swap_mb, ephemeral_mb, ephemeral_format, image_path, node_uuid, preserve_ephemeral=preserve_ephemeral, configdrive=configdrive, boot_option=boot_option, boot_mode=boot_mode, disk_label=disk_label) return uuid_dict_returned
def _write_partition_image(image, image_info, device): """Call disk_util to create partition and write the partition image. :param image: Local path to image file to be written to the partition. If ``None``, the image is not populated. :param image_info: Image information dictionary. :param device: The device name, as a string, on which to store the image. Example: '/dev/sda' :raises: InvalidCommandParamsError if the partition is too small for the provided image. :raises: ImageWriteError if writing the image to disk encounters any error. """ # Retrieve the cached node as it has the latest information # and allows us to also sanity check the deployment so we don't end # up writing MBR when we're in UEFI mode. cached_node = hardware.get_cached_node() node_uuid = image_info.get('node_uuid') preserve_ep = image_info['preserve_ephemeral'] configdrive = image_info['configdrive'] boot_option = image_info.get('boot_option', 'local') boot_mode = utils.get_node_boot_mode(cached_node) disk_label = utils.get_partition_table_type_from_specs(cached_node) root_mb = image_info['root_mb'] cpu_arch = hardware.dispatch_to_managers('get_cpus').architecture if image is not None: image_mb = disk_utils.get_image_mb(image) if image_mb > int(root_mb): msg = ('Root partition is too small for requested image. Image ' 'virtual size: {} MB, Root size: {} MB').format( image_mb, root_mb) raise errors.InvalidCommandParamsError(msg) try: return disk_utils.work_on_disk(device, root_mb, image_info['swap_mb'], image_info['ephemeral_mb'], image_info['ephemeral_format'], image, node_uuid, preserve_ephemeral=preserve_ep, configdrive=configdrive, boot_option=boot_option, boot_mode=boot_mode, disk_label=disk_label, cpu_arch=cpu_arch) except processutils.ProcessExecutionError as e: raise errors.ImageWriteError(device, e.exit_code, e.stdout, e.stderr)
def check_image_size(task): """Check if the requested image is larger than the root partition size. :param task: a TaskManager instance containing the node to act on. :raises: InstanceDeployFailure if size of the image is greater than root partition. """ i_info = deploy_utils.parse_instance_info(task.node) image_path = _get_image_file_path(task.node.uuid) image_mb = disk_utils.get_image_mb(image_path) root_mb = 1024 * int(i_info['root_gb']) if image_mb > root_mb: msg = (_('Root partition is too small for requested image. Image ' 'virtual size: %(image_mb)d MB, Root size: %(root_mb)d MB') % {'image_mb': image_mb, 'root_mb': root_mb}) raise exception.InstanceDeployFailure(msg)
def check_image_size(task): """Check if the requested image is larger than the root partition size. :param task: a TaskManager instance containing the node to act on. :raises: InstanceDeployFailure if size of the image is greater than root partition. """ i_info = parse_instance_info(task.node) image_path = _get_image_file_path(task.node.uuid) image_mb = disk_utils.get_image_mb(image_path) root_mb = 1024 * int(i_info['root_gb']) if image_mb > root_mb: msg = (_('Root partition is too small for requested image. Image ' 'virtual size: %(image_mb)d MB, Root size: %(root_mb)d MB') % {'image_mb': image_mb, 'root_mb': root_mb}) raise exception.InstanceDeployFailure(msg)
def _write_partition_image(image, image_info, device): """Call disk_util to create partition and write the partition image. :param image: Local path to image file to be written to the partition. If ``None``, the image is not populated. :param image_info: Image information dictionary. :param device: The device name, as a string, on which to store the image. Example: '/dev/sda' :raises: InvalidCommandParamsError if the partition is too small for the provided image. :raises: ImageWriteError if writing the image to disk encounters any error. """ node_uuid = image_info.get('node_uuid') preserve_ep = image_info['preserve_ephemeral'] configdrive = image_info['configdrive'] boot_option = image_info.get('boot_option', 'netboot') boot_mode = image_info.get('deploy_boot_mode', 'bios') disk_label = image_info.get('disk_label', 'msdos') root_mb = image_info['root_mb'] cpu_arch = hardware.dispatch_to_managers('get_cpus').architecture if image is not None: image_mb = disk_utils.get_image_mb(image) if image_mb > int(root_mb): msg = ('Root partition is too small for requested image. Image ' 'virtual size: {} MB, Root size: {} MB').format(image_mb, root_mb) raise errors.InvalidCommandParamsError(msg) try: return disk_utils.work_on_disk(device, root_mb, image_info['swap_mb'], image_info['ephemeral_mb'], image_info['ephemeral_format'], image, node_uuid, preserve_ephemeral=preserve_ep, configdrive=configdrive, boot_option=boot_option, boot_mode=boot_mode, disk_label=disk_label, cpu_arch=cpu_arch) except processutils.ProcessExecutionError as e: raise errors.ImageWriteError(device, e.exit_code, e.stdout, e.stderr)
def _write_partition_image(image, image_info, device): """Call disk_util to create partition and write the partition image. :param image: Local path to image file to be written to the partition. :param image_info: Image information dictionary. :param device: The device name, as a string, on which to store the image. Example: '/dev/sda' :raises: InvalidCommandParamsError if the partition is too small for the provided image. :raises: ImageWriteError if writing the image to disk encounters any error. """ node_uuid = image_info.get('node_uuid') preserve_ep = image_info['preserve_ephemeral'] configdrive = image_info['configdrive'] boot_option = image_info.get('boot_option', 'netboot') boot_mode = image_info.get('deploy_boot_mode', 'bios') disk_label = image_info.get('disk_label', 'msdos') image_mb = disk_utils.get_image_mb(image) root_mb = image_info['root_mb'] cpu_arch = hardware.dispatch_to_managers('get_cpus').architecture if image_mb > int(root_mb): msg = ('Root partition is too small for requested image. Image ' 'virtual size: {} MB, Root size: {} MB').format( image_mb, root_mb) raise errors.InvalidCommandParamsError(msg) try: return disk_utils.work_on_disk(device, root_mb, image_info['swap_mb'], image_info['ephemeral_mb'], image_info['ephemeral_format'], image, node_uuid, preserve_ephemeral=preserve_ep, configdrive=configdrive, boot_option=boot_option, boot_mode=boot_mode, disk_label=disk_label, cpu_arch=cpu_arch) except processutils.ProcessExecutionError as e: raise errors.ImageWriteError(device, e.exit_code, e.stdout, e.stderr)
def test_get_image_mb(self, mock_qinfo, mock_getsize): mb = 1024 * 1024 mock_getsize.return_value = 0 type(mock_qinfo.return_value).virtual_size = mock.PropertyMock( return_value=0) self.assertEqual(0, disk_utils.get_image_mb('x', False)) self.assertEqual(0, disk_utils.get_image_mb('x', True)) mock_getsize.return_value = 1 type(mock_qinfo.return_value).virtual_size = mock.PropertyMock( return_value=1) self.assertEqual(1, disk_utils.get_image_mb('x', False)) self.assertEqual(1, disk_utils.get_image_mb('x', True)) mock_getsize.return_value = mb type(mock_qinfo.return_value).virtual_size = mock.PropertyMock( return_value=mb) self.assertEqual(1, disk_utils.get_image_mb('x', False)) self.assertEqual(1, disk_utils.get_image_mb('x', True)) mock_getsize.return_value = mb + 1 type(mock_qinfo.return_value).virtual_size = mock.PropertyMock( return_value=mb + 1) self.assertEqual(2, disk_utils.get_image_mb('x', False)) self.assertEqual(2, disk_utils.get_image_mb('x', True))
def test_get_image_mb(self, mock_qinfo, mock_getsize): mb = 1024 * 1024 mock_getsize.return_value = 0 type(mock_qinfo.return_value).virtual_size = mock.PropertyMock( return_value=0) self.assertEqual(0, disk_utils.get_image_mb('x', False)) self.assertEqual(0, disk_utils.get_image_mb('x', True)) mock_getsize.return_value = 1 type(mock_qinfo.return_value).virtual_size = mock.PropertyMock( return_value=1) self.assertEqual(1, disk_utils.get_image_mb('x', False)) self.assertEqual(1, disk_utils.get_image_mb('x', True)) mock_getsize.return_value = mb type(mock_qinfo.return_value).virtual_size = mock.PropertyMock( return_value=mb) self.assertEqual(1, disk_utils.get_image_mb('x', False)) self.assertEqual(1, disk_utils.get_image_mb('x', True)) mock_getsize.return_value = mb + 1 type(mock_qinfo.return_value).virtual_size = mock.PropertyMock( return_value=mb + 1) self.assertEqual(2, disk_utils.get_image_mb('x', False)) self.assertEqual(2, disk_utils.get_image_mb('x', True))
def check_image_size(task): """Check if the requested image is larger than the root partition size. Does nothing for whole-disk images. :param task: a TaskManager instance containing the node to act on. :raises: InstanceDeployFailure if size of the image is greater than root partition. """ if task.node.driver_internal_info['is_whole_disk_image']: # The root partition is already created and populated, no use # validating its size return i_info = deploy_utils.parse_instance_info(task.node) image_path = deploy_utils._get_image_file_path(task.node.uuid) image_mb = disk_utils.get_image_mb(image_path) root_mb = 1024 * int(i_info['root_gb']) if image_mb > root_mb: msg = (_('Root partition is too small for requested image. Image ' 'virtual size: %(image_mb)d MB, Root size: %(root_mb)d MB') % {'image_mb': image_mb, 'root_mb': root_mb}) raise exception.InstanceDeployFailure(msg)