"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "ironic/common/images.py" between
ironic-16.0.2.tar.gz and ironic-16.0.3.tar.gz

About: OpenStack Ironic (Optional Service: Bare-Metal Provisioning) aims to provision bare metal machines instead of virtual machines, forked from the Nova baremetal driver.
The "Victoria" series (latest release).

images.py  (ironic-16.0.2):images.py  (ironic-16.0.3)
skipping to change at line 22 skipping to change at line 22
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
""" """
Handling of VM disk images. Handling of VM disk images.
""" """
import contextlib
import os import os
import shutil import shutil
from ironic_lib import disk_utils from ironic_lib import disk_utils
from ironic_lib import utils as ironic_utils from ironic_lib import utils as ironic_utils
from oslo_concurrency import processutils from oslo_concurrency import processutils
from oslo_log import log as logging from oslo_log import log as logging
from oslo_utils import fileutils from oslo_utils import fileutils
from ironic.common import exception from ironic.common import exception
skipping to change at line 50 skipping to change at line 49
def _create_root_fs(root_directory, files_info): def _create_root_fs(root_directory, files_info):
"""Creates a filesystem root in given directory. """Creates a filesystem root in given directory.
Given a mapping of absolute path of files to their relative paths Given a mapping of absolute path of files to their relative paths
within the filesystem, this method copies the files to their within the filesystem, this method copies the files to their
destination. destination.
:param root_directory: the filesystem root directory. :param root_directory: the filesystem root directory.
:param files_info: A dict containing absolute path of file to be copied :param files_info: A dict containing absolute path of file to be copied
-> relative path within the vfat image. For example:: or its content as bytes -> relative path within
the vfat image. For example::
{ {
'/absolute/path/to/file' -> 'relative/path/within/root' '/absolute/path/to/file': 'relative/path/within/root',
b'{"some": "json"}': 'another/relative/path'
... ...
} }
:raises: OSError, if creation of any directory failed. :raises: OSError, if creation of any directory failed.
:raises: IOError, if copying any of the files failed. :raises: IOError, if copying any of the files failed.
""" """
for src_file, path in files_info.items(): for src_file, path in files_info.items():
target_file = os.path.join(root_directory, path) target_file = os.path.join(root_directory, path)
dirname = os.path.dirname(target_file) dirname = os.path.dirname(target_file)
if not os.path.exists(dirname): if dirname:
os.makedirs(dirname) os.makedirs(dirname, exist_ok=True)
shutil.copyfile(src_file, target_file) if isinstance(src_file, bytes):
with open(target_file, 'wb') as fp:
fp.write(src_file)
else:
shutil.copyfile(src_file, target_file)
def _umount_without_raise(mount_dir): def _umount_without_raise(mount_dir):
"""Helper method to umount without raise.""" """Helper method to umount without raise."""
try: try:
utils.umount(mount_dir) utils.umount(mount_dir)
except processutils.ProcessExecutionError: except processutils.ProcessExecutionError:
pass pass
def create_vfat_image(output_file, files_info=None, parameters=None, def create_vfat_image(output_file, files_info=None, parameters=None,
parameters_file='parameters.txt', fs_size_kib=100): parameters_file='parameters.txt', fs_size_kib=100):
skipping to change at line 153 skipping to change at line 158
as the kernel cmdline. as the kernel cmdline.
:param template: the path of the config template file. :param template: the path of the config template file.
:param options: a dictionary of keywords which need to be replaced in :param options: a dictionary of keywords which need to be replaced in
template file to generate a proper config file. template file to generate a proper config file.
:returns: a string containing the contents of the isolinux configuration :returns: a string containing the contents of the isolinux configuration
file. file.
""" """
options.update({'kernel_params': ' '.join(kernel_params or [])}) options.update({'kernel_params': ' '.join(kernel_params or [])})
return utils.render_template(template, options) return utils.render_template(template, options)
def _read_dir(root_dir, prefix_dir=None): def _label(files_info):
"""Gather files under given directory. """Get a suitable label for the files.
:param root_dir: a directory to traverse.
:returns: a dict mapping absolute paths to relative to the `root_dir`.
"""
files_info = {}
if not prefix_dir:
prefix_dir = root_dir
for entry in os.listdir(root_dir):
path = os.path.join(root_dir, entry)
if os.path.isdir(path):
files_info.update(_read_dir(path, prefix_dir))
else:
files_info[path] = path[len(prefix_dir) + 1:]
return files_info
@contextlib.contextmanager Returns "config-2" if the openstack metadata is present.
def _collect_files(image_path):
"""Mount image and return a dictionary of paths found there.
Mounts given image under a temporary directory, walk its contents
and produce a dictionary of absolute->relative paths found on the
image.
:param image_path: ISO9660 or FAT-formatted image to mount.
:raises: ImageCreationFailed, if image inspection failed.
:returns: a dict mapping absolute paths to relative to the mount point.
""" """
if not image_path: if any(x.startswith('openstack/') for x in files_info.values()):
yield {} return 'config-2'
return else:
return 'VMEDIA_BOOT_ISO'
with utils.tempdir() as mount_dir:
try:
utils.mount(image_path, mount_dir, '-o', 'loop')
except processutils.ProcessExecutionError as e:
LOG.exception("Mounting filesystem image %(image)s "
"failed", {'image': image_path})
raise exception.ImageCreationFailed(image_type='iso', error=e)
try:
yield _read_dir(mount_dir)
except EnvironmentError as e:
LOG.exception(
"Examining image %(images)s failed: ", {'image': image_path})
_umount_without_raise(mount_dir)
raise exception.ImageCreationFailed(image_type='iso', error=e)
_umount_without_raise(mount_dir)
def create_isolinux_image_for_bios( def create_isolinux_image_for_bios(
output_file, kernel, ramdisk, kernel_params=None, configdrive=None): output_file, kernel, ramdisk, kernel_params=None, inject_files=None):
"""Creates an isolinux image on the specified file. """Creates an isolinux image on the specified file.
Copies the provided kernel, ramdisk to a directory, generates the isolinux Copies the provided kernel, ramdisk to a directory, generates the isolinux
configuration file using the kernel parameters provided, and then generates configuration file using the kernel parameters provided, and then generates
a bootable ISO image. a bootable ISO image.
:param output_file: the path to the file where the iso image needs to be :param output_file: the path to the file where the iso image needs to be
created. created.
:param kernel: the kernel to use. :param kernel: the kernel to use.
:param ramdisk: the ramdisk to use. :param ramdisk: the ramdisk to use.
:param kernel_params: a list of strings(each element being a string like :param kernel_params: a list of strings(each element being a string like
'K=V' or 'K' or combination of them like 'K1=V1,K2,...') to be added 'K=V' or 'K' or combination of them like 'K1=V1,K2,...') to be added
as the kernel cmdline. as the kernel cmdline.
:param configdrive: ISO9660 or FAT-formatted OpenStack config drive :param inject_files: Mapping of local source file paths to their location
image. This image will be written onto the built ISO image. Optional. on the final ISO image.
:raises: ImageCreationFailed, if image creation failed while copying files :raises: ImageCreationFailed, if image creation failed while copying files
or while running command to generate iso. or while running command to generate iso.
""" """
ISOLINUX_BIN = 'isolinux/isolinux.bin' ISOLINUX_BIN = 'isolinux/isolinux.bin'
ISOLINUX_CFG = 'isolinux/isolinux.cfg' ISOLINUX_CFG = 'isolinux/isolinux.cfg'
LDLINUX_SRC_DIRS = ['/usr/lib/syslinux/modules/bios', LDLINUX_SRC_DIRS = ['/usr/lib/syslinux/modules/bios',
'/usr/share/syslinux'] '/usr/share/syslinux']
LDLINUX_BIN = 'isolinux/ldlinux.c32' LDLINUX_BIN = 'isolinux/ldlinux.c32'
options = {'kernel': '/vmlinuz', 'ramdisk': '/initrd'} options = {'kernel': '/vmlinuz', 'ramdisk': '/initrd'}
with utils.tempdir() as tmpdir: with utils.tempdir() as tmpdir:
files_info = { files_info = {
kernel: 'vmlinuz', kernel: 'vmlinuz',
ramdisk: 'initrd', ramdisk: 'initrd',
CONF.isolinux_bin: ISOLINUX_BIN, CONF.isolinux_bin: ISOLINUX_BIN,
} }
if inject_files:
files_info.update(inject_files)
# ldlinux.c32 is required for syslinux 5.0 or later. # ldlinux.c32 is required for syslinux 5.0 or later.
if CONF.ldlinux_c32: if CONF.ldlinux_c32:
ldlinux_src = CONF.ldlinux_c32 ldlinux_src = CONF.ldlinux_c32
else: else:
for directory in LDLINUX_SRC_DIRS: for directory in LDLINUX_SRC_DIRS:
ldlinux_src = os.path.join(directory, 'ldlinux.c32') ldlinux_src = os.path.join(directory, 'ldlinux.c32')
if os.path.isfile(ldlinux_src): if os.path.isfile(ldlinux_src):
break break
else: else:
ldlinux_src = None ldlinux_src = None
if ldlinux_src: if ldlinux_src:
files_info[ldlinux_src] = LDLINUX_BIN files_info[ldlinux_src] = LDLINUX_BIN
with _collect_files(configdrive) as cfgdrv_files: try:
files_info.update(cfgdrv_files) _create_root_fs(tmpdir, files_info)
try:
_create_root_fs(tmpdir, files_info)
except EnvironmentError as e: except EnvironmentError as e:
LOG.exception("Creating the filesystem root failed.") LOG.exception("Creating the filesystem root failed.")
raise exception.ImageCreationFailed(image_type='iso', error=e) raise exception.ImageCreationFailed(image_type='iso', error=e)
cfg = _generate_cfg(kernel_params, cfg = _generate_cfg(kernel_params,
CONF.isolinux_config_template, options) CONF.isolinux_config_template, options)
isolinux_cfg = os.path.join(tmpdir, ISOLINUX_CFG) isolinux_cfg = os.path.join(tmpdir, ISOLINUX_CFG)
utils.write_to_file(isolinux_cfg, cfg) utils.write_to_file(isolinux_cfg, cfg)
try: try:
utils.execute('mkisofs', '-r', '-V', utils.execute('mkisofs', '-r', '-V', _label(files_info),
'config-2' if configdrive else 'VMEDIA_BOOT_ISO',
'-cache-inodes', '-J', '-l', '-no-emul-boot', '-cache-inodes', '-J', '-l', '-no-emul-boot',
'-boot-load-size', '4', '-boot-info-table', '-boot-load-size', '4', '-boot-info-table',
'-b', ISOLINUX_BIN, '-o', output_file, tmpdir) '-b', ISOLINUX_BIN, '-o', output_file, tmpdir)
except processutils.ProcessExecutionError as e: except processutils.ProcessExecutionError as e:
LOG.exception("Creating ISO image failed.") LOG.exception("Creating ISO image failed.")
raise exception.ImageCreationFailed(image_type='iso', error=e) raise exception.ImageCreationFailed(image_type='iso', error=e)
def create_esp_image_for_uefi( def create_esp_image_for_uefi(
output_file, kernel, ramdisk, deploy_iso=None, esp_image=None, output_file, kernel, ramdisk, deploy_iso=None, esp_image=None,
kernel_params=None, configdrive=None): kernel_params=None, inject_files=None):
"""Creates an ESP image on the specified file. """Creates an ESP image on the specified file.
Copies the provided kernel, ramdisk and EFI system partition image (ESP) to Copies the provided kernel, ramdisk and EFI system partition image (ESP) to
a directory, generates the grub configuration file using kernel parameters a directory, generates the grub configuration file using kernel parameters
and then generates a bootable ISO image for UEFI. and then generates a bootable ISO image for UEFI.
:param output_file: the path to the file where the iso image needs to be :param output_file: the path to the file where the iso image needs to be
created. created.
:param kernel: the kernel to use. :param kernel: the kernel to use.
:param ramdisk: the ramdisk to use. :param ramdisk: the ramdisk to use.
:param deploy_iso: deploy ISO image to extract EFI system partition image :param deploy_iso: deploy ISO image to extract EFI system partition image
from. If not specified, the `esp_image` option is required. from. If not specified, the `esp_image` option is required.
:param esp_image: FAT12/16/32-formatted EFI system partition image :param esp_image: FAT12/16/32-formatted EFI system partition image
containing the EFI boot loader (e.g. GRUB2) for each hardware containing the EFI boot loader (e.g. GRUB2) for each hardware
architecture to boot. This image will be embedded into the ISO image. architecture to boot. This image will be embedded into the ISO image.
If not specified, the `deploy_iso` option is required. If not specified, the `deploy_iso` option is required.
:param kernel_params: a list of strings(each element being a string like :param kernel_params: a list of strings(each element being a string like
'K=V' or 'K' or combination of them like 'K1=V1,K2,...') to be added 'K=V' or 'K' or combination of them like 'K1=V1,K2,...') to be added
as the kernel cmdline. as the kernel cmdline.
:param configdrive: ISO9660 or FAT-formatted OpenStack config drive :param inject_files: Mapping of local source file paths to their location
image. This image will be written onto the built ISO image. Optional. on the final ISO image.
:raises: ImageCreationFailed, if image creation failed while copying files :raises: ImageCreationFailed, if image creation failed while copying files
or while running command to generate iso. or while running command to generate iso.
""" """
EFIBOOT_LOCATION = 'boot/grub/efiboot.img' EFIBOOT_LOCATION = 'boot/grub/efiboot.img'
grub_options = {'linux': '/vmlinuz', 'initrd': '/initrd'} grub_options = {'linux': '/vmlinuz', 'initrd': '/initrd'}
with utils.tempdir() as tmpdir: with utils.tempdir() as tmpdir:
files_info = { files_info = {
kernel: 'vmlinuz', kernel: 'vmlinuz',
ramdisk: 'initrd', ramdisk: 'initrd',
} }
if inject_files:
files_info.update(inject_files)
with utils.tempdir() as mountdir: with utils.tempdir() as mountdir:
# Open the deploy iso used to initiate deploy and copy the # Open the deploy iso used to initiate deploy and copy the
# efiboot.img i.e. boot loader to the current temporary # efiboot.img i.e. boot loader to the current temporary
# directory. # directory.
if deploy_iso and not esp_image: if deploy_iso and not esp_image:
uefi_path_info, e_img_rel_path, grub_rel_path = ( uefi_path_info, e_img_rel_path, grub_rel_path = (
_mount_deploy_iso(deploy_iso, mountdir)) _mount_deploy_iso(deploy_iso, mountdir))
grub_cfg = os.path.join(tmpdir, grub_rel_path) grub_cfg = os.path.join(tmpdir, grub_rel_path)
skipping to change at line 354 skipping to change at line 312
} }
else: else:
msg = _('Neither deploy ISO nor ESP image configured or ' msg = _('Neither deploy ISO nor ESP image configured or '
'both of them configured') 'both of them configured')
raise exception.ImageCreationFailed( raise exception.ImageCreationFailed(
image_type='iso', error=msg) image_type='iso', error=msg)
files_info.update(uefi_path_info) files_info.update(uefi_path_info)
with _collect_files(configdrive) as cfgdrv_files: try:
files_info.update(cfgdrv_files) _create_root_fs(tmpdir, files_info)
try: except EnvironmentError as e:
_create_root_fs(tmpdir, files_info) LOG.exception("Creating the filesystem root failed.")
raise exception.ImageCreationFailed(
image_type='iso', error=e)
except EnvironmentError as e: finally:
LOG.exception("Creating the filesystem root failed.") if deploy_iso:
raise exception.ImageCreationFailed( _umount_without_raise(mountdir)
image_type='iso', error=e)
finally:
if deploy_iso:
_umount_without_raise(mountdir)
# Generate and copy grub config file. # Generate and copy grub config file.
grub_conf = _generate_cfg(kernel_params, grub_conf = _generate_cfg(kernel_params,
CONF.grub_config_template, grub_options) CONF.grub_config_template, grub_options)
utils.write_to_file(grub_cfg, grub_conf) utils.write_to_file(grub_cfg, grub_conf)
# Create the boot_iso. # Create the boot_iso.
try: try:
utils.execute('mkisofs', '-r', '-V', utils.execute('mkisofs', '-r', '-V', _label(files_info),
'config-2' if configdrive else 'VMEDIA_BOOT_ISO',
'-l', '-e', e_img_rel_path, '-no-emul-boot', '-l', '-e', e_img_rel_path, '-no-emul-boot',
'-o', output_file, tmpdir) '-o', output_file, tmpdir)
except processutils.ProcessExecutionError as e: except processutils.ProcessExecutionError as e:
LOG.exception("Creating ISO image failed.") LOG.exception("Creating ISO image failed.")
raise exception.ImageCreationFailed(image_type='iso', error=e) raise exception.ImageCreationFailed(image_type='iso', error=e)
# NOTE(etingof): backward compatibility
create_isolinux_image_for_uefi = create_esp_image_for_uefi
def fetch(context, image_href, path, force_raw=False): def fetch(context, image_href, path, force_raw=False):
# TODO(vish): Improve context handling and add owner and auth data # TODO(vish): Improve context handling and add owner and auth data
# when it is added to glance. Right now there is no # when it is added to glance. Right now there is no
# auth checking in glance, so we assume that access was # auth checking in glance, so we assume that access was
# checked before we got here. # checked before we got here.
image_service = service.get_image_service(image_href, image_service = service.get_image_service(image_href,
context=context) context=context)
LOG.debug("Using %(image_service)s to download image %(image_href)s.", LOG.debug("Using %(image_service)s to download image %(image_href)s.",
{'image_service': image_service.__class__, {'image_service': image_service.__class__,
'image_href': image_href}) 'image_href': image_href})
skipping to change at line 510 skipping to change at line 461
""" """
glance_service = service.GlanceImageService(context=context) glance_service = service.GlanceImageService(context=context)
image_properties = glance_service.show(image_uuid) image_properties = glance_service.show(image_uuid)
LOG.debug('Got image info: %(info)s for image %(image_uuid)s.', LOG.debug('Got image info: %(info)s for image %(image_uuid)s.',
{'info': image_properties, 'image_uuid': image_uuid}) {'info': image_properties, 'image_uuid': image_uuid})
return glance_service.swift_temp_url(image_properties) return glance_service.swift_temp_url(image_properties)
def create_boot_iso(context, output_filename, kernel_href, def create_boot_iso(context, output_filename, kernel_href,
ramdisk_href, deploy_iso_href=None, esp_image_href=None, ramdisk_href, deploy_iso_href=None, esp_image_href=None,
root_uuid=None, kernel_params=None, boot_mode=None, root_uuid=None, kernel_params=None, boot_mode=None,
configdrive_href=None, base_iso=None): base_iso=None, inject_files=None):
"""Creates a bootable ISO image for a node. """Creates a bootable ISO image for a node.
Given the hrefs for kernel, ramdisk, root partition's UUID and Given the hrefs for kernel, ramdisk, root partition's UUID and
kernel cmdline arguments, this method fetches the kernel and ramdisk, kernel cmdline arguments, this method fetches the kernel and ramdisk,
and builds a bootable ISO image that can be used to boot up the and builds a bootable ISO image that can be used to boot up the
baremetal node. baremetal node.
:param context: context :param context: context
:param output_filename: the absolute path of the output ISO file :param output_filename: the absolute path of the output ISO file
:param kernel_href: URL or glance uuid of the kernel to use :param kernel_href: URL or glance uuid of the kernel to use
skipping to change at line 534 skipping to change at line 485
the `esp_image_href` option must be present if UEFI-bootable the `esp_image_href` option must be present if UEFI-bootable
ISO is desired. ISO is desired.
:param esp_image_href: URL or glance UUID of FAT12/16/32-formatted EFI :param esp_image_href: URL or glance UUID of FAT12/16/32-formatted EFI
system partition image containing the EFI boot loader (e.g. GRUB2) system partition image containing the EFI boot loader (e.g. GRUB2)
for each hardware architecture to boot. This image will be written for each hardware architecture to boot. This image will be written
onto the ISO image. If not specified, the `deploy_iso_href` option onto the ISO image. If not specified, the `deploy_iso_href` option
is only required for building UEFI-bootable ISO. is only required for building UEFI-bootable ISO.
:param kernel_params: a string containing whitespace separated values :param kernel_params: a string containing whitespace separated values
kernel cmdline arguments of the form K=V or K (optional). kernel cmdline arguments of the form K=V or K (optional).
:boot_mode: the boot mode in which the deploy is to happen. :boot_mode: the boot mode in which the deploy is to happen.
:param configdrive_href: URL to ISO9660 or FAT-formatted OpenStack config
drive image. This image will be embedded into the built ISO image.
Optional.
:param base_iso: URL or glance UUID of a to be used as an override of :param base_iso: URL or glance UUID of a to be used as an override of
what should be retrieved for to use, instead of building an ISO what should be retrieved for to use, instead of building an ISO
bootable ramdisk. bootable ramdisk.
:param inject_files: Mapping of local source file paths to their location
on the final ISO image.
:raises: ImageCreationFailed, if creating boot ISO failed. :raises: ImageCreationFailed, if creating boot ISO failed.
""" """
with utils.tempdir() as tmpdir: with utils.tempdir() as tmpdir:
if base_iso: if base_iso:
# NOTE(TheJulia): Eventually we want to use the creation method # NOTE(TheJulia): Eventually we want to use the creation method
# to perform the massaging of the image, because oddly enough # to perform the massaging of the image, because oddly enough
# we need to do all the same basic things, just a little # we need to do all the same basic things, just a little
# differently. # differently.
fetch(context, base_iso, output_filename) fetch(context, base_iso, output_filename)
# Temporary, return to the caller until we support the combined # Temporary, return to the caller until we support the combined
# operation. # operation.
return return
else: else:
kernel_path = os.path.join(tmpdir, kernel_href.split('/')[-1]) kernel_path = os.path.join(tmpdir, kernel_href.split('/')[-1])
ramdisk_path = os.path.join(tmpdir, ramdisk_href.split('/')[-1]) ramdisk_path = os.path.join(tmpdir, ramdisk_href.split('/')[-1])
fetch(context, kernel_href, kernel_path) fetch(context, kernel_href, kernel_path)
fetch(context, ramdisk_href, ramdisk_path) fetch(context, ramdisk_href, ramdisk_path)
if configdrive_href:
configdrive_path = os.path.join(
tmpdir, configdrive_href.split('/')[-1])
fetch(context, configdrive_href, configdrive_path)
else:
configdrive_path = None
params = [] params = []
if root_uuid: if root_uuid:
params.append('root=UUID=%s' % root_uuid) params.append('root=UUID=%s' % root_uuid)
if kernel_params: if kernel_params:
params.append(kernel_params) params.append(kernel_params)
if boot_mode == 'uefi': if boot_mode == 'uefi':
deploy_iso_path = esp_image_path = None deploy_iso_path = esp_image_path = None
skipping to change at line 596 skipping to change at line 538
elif CONF.esp_image: elif CONF.esp_image:
esp_image_path = CONF.esp_image esp_image_path = CONF.esp_image
# TODO(TheJulia): we should opportunisticly try to make bios # TODO(TheJulia): we should opportunisticly try to make bios
# bootable and UEFI. In other words, collapse a lot of this # bootable and UEFI. In other words, collapse a lot of this
# path since they are not mutually exclusive. # path since they are not mutually exclusive.
# UEFI boot mode, but Network iPXE -> ISO means bios bootable # UEFI boot mode, but Network iPXE -> ISO means bios bootable
# contents are still required. # contents are still required.
create_esp_image_for_uefi( create_esp_image_for_uefi(
output_filename, kernel_path, ramdisk_path, output_filename, kernel_path, ramdisk_path,
deploy_iso=deploy_iso_path, esp_image=esp_image_path, deploy_iso=deploy_iso_path, esp_image=esp_image_path,
kernel_params=params, configdrive=configdrive_path) kernel_params=params, inject_files=inject_files)
else: else:
create_isolinux_image_for_bios( create_isolinux_image_for_bios(
output_filename, kernel_path, ramdisk_path, output_filename, kernel_path, ramdisk_path,
kernel_params=params, configdrive=configdrive_path) kernel_params=params, inject_files=inject_files)
def is_whole_disk_image(ctx, instance_info): def is_whole_disk_image(ctx, instance_info):
"""Find out if the image is a partition image or a whole disk image. """Find out if the image is a partition image or a whole disk image.
:param ctx: an admin context :param ctx: an admin context
:param instance_info: a node's instance info dict :param instance_info: a node's instance info dict
:returns: True for whole disk images and False for partition images :returns: True for whole disk images and False for partition images
and None on no image_source or Error. and None on no image_source or Error.
""" """
 End of changes. 28 change blocks. 
107 lines changed or deleted 49 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)