def qemu_img_info(path, format=None): """Return an object containing the parsed output from qemu-img info.""" # TODO(mikal): this code should not be referring to a libvirt specific # flag. if not os.path.exists(path) and CONF.libvirt.images_type != 'rbd': raise exception.DiskNotFound(location=path) try: # The following check is about ploop images that reside within # directories and always have DiskDescriptor.xml file beside them if (os.path.isdir(path) and os.path.exists(os.path.join(path, "DiskDescriptor.xml"))): path = os.path.join(path, "root.hds") cmd = ('env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info', path) if format is not None: cmd = cmd + ('-f', format) # Check to see if the qemu version is >= 2.10 because if so, we need # to add the --force-share flag. if QEMU_VERSION and operator.ge(QEMU_VERSION, QEMU_VERSION_REQ_SHARED): cmd = cmd + ('--force-share', ) out, err = processutils.execute(*cmd, prlimit=QEMU_IMG_LIMITS) except processutils.ProcessExecutionError as exp: if exp.exit_code == -9: # this means we hit prlimits, make the exception more specific msg = (_("qemu-img aborted by prlimits when inspecting " "%(path)s : %(exp)s") % { 'path': path, 'exp': exp }) elif exp.exit_code == 1 and 'No such file or directory' in exp.stderr: # The os.path.exists check above can race so this is a simple # best effort at catching that type of failure and raising a more # specific error. raise exception.DiskNotFound(location=path) else: msg = (_("qemu-img failed to execute on %(path)s : %(exp)s") % { 'path': path, 'exp': exp }) raise exception.InvalidDiskInfo(reason=msg) if not out: msg = (_("Failed to run qemu-img info on %(path)s : %(error)s") % { 'path': path, 'error': err }) raise exception.InvalidDiskInfo(reason=msg) return imageutils.QemuImgInfo(out)
def get_disk_path(): disk_paths = set() volume_mappings = self._get_fc_volume_mappings(connection_info) if not volume_mappings: LOG.debug( "Could not find FC mappings for volume " "%(conn_info)s. Rescanning disks.", dict(conn_info=connection_info)) self._diskutils.rescan_disks() else: # Because of MPIO, we may not be able to get the device name # from a specific mapping if the disk was accessed through # an other HBA at that moment. In that case, the device name # will show up as an empty string. for mapping in volume_mappings: device_name = mapping['device_name'] if device_name: disk_paths.add(device_name) if disk_paths: self._check_device_paths(disk_paths) disk_path = list(disk_paths)[0] return self._get_mounted_disk_path_by_dev_name(disk_path) err_msg = _("Could not find the physical disk " "path for the requested volume.") raise exception.DiskNotFound(err_msg)
def qemu_img_info(path, format=None): """Return an object containing the parsed output from qemu-img info.""" # TODO(mikal): this code should not be referring to a libvirt specific # flag. if not os.path.exists(path) and CONF.libvirt.images_type != 'rbd': raise exception.DiskNotFound(location=path) try: # The following check is about ploop images that reside within # directories and always have DiskDescriptor.xml file beside them if (os.path.isdir(path) and os.path.exists(os.path.join(path, "DiskDescriptor.xml"))): path = os.path.join(path, "root.hds") cmd = ('env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info', path) if format is not None: cmd = cmd + ('-f', format) out, err = utils.execute(*cmd, prlimit=QEMU_IMG_LIMITS) except processutils.ProcessExecutionError as exp: # this means we hit prlimits, make the exception more specific if exp.exit_code == -9: msg = (_("qemu-img aborted by prlimits when inspecting " "%(path)s : %(exp)s") % {'path': path, 'exp': exp}) else: msg = (_("qemu-img failed to execute on %(path)s : %(exp)s") % {'path': path, 'exp': exp}) raise exception.InvalidDiskInfo(reason=msg) if not out: msg = (_("Failed to run qemu-img info on %(path)s : %(error)s") % {'path': path, 'error': err}) raise exception.InvalidDiskInfo(reason=msg) return imageutils.QemuImgInfo(out)
def privileged_qemu_img_info(path, format=None, output_format='json'): """Return an object containing the parsed output from qemu-img info.""" if not os.path.exists(path) and not path.startswith('rbd:'): raise exception.DiskNotFound(location=path) info = nova.privsep.qemu.privileged_qemu_img_info(path, format=format) return imageutils.QemuImgInfo(info, format='json')
def get_disk_resource_path(self, connection_info): for attempt in range(self._MAX_RESCAN_COUNT): disk_paths = set() self._diskutils.rescan_disks() volume_mappings = self._get_fc_volume_mappings(connection_info) LOG.debug( "Retrieved volume mappings %(vol_mappings)s " "for volume %(conn_info)s", dict(vol_mappings=volume_mappings, conn_info=connection_info)) # Because of MPIO, we may not be able to get the device name # from a specific mapping if the disk was accessed through # an other HBA at that moment. In that case, the device name # will show up as an empty string. for mapping in volume_mappings: device_name = mapping['device_name'] if device_name: disk_paths.add(device_name) if disk_paths: self._check_device_paths(disk_paths) disk_path = list(disk_paths)[0] return self._get_mounted_disk_path_by_dev_name(disk_path) err_msg = _("Could not find the physical disk " "path for the requested volume.") raise exception.DiskNotFound(err_msg)
def finish_revert_migration(self, context, instance, network_info, block_device_info=None, power_on=True): LOG.debug("finish_revert_migration called", instance=instance) instance_name = instance.name self._revert_migration_files(instance_name) image_meta = objects.ImageMeta.from_instance(instance) vm_gen = self._vmops.get_image_vm_generation(instance.uuid, image_meta) self._block_dev_man.validate_and_update_bdi(instance, image_meta, vm_gen, block_device_info) root_device = block_device_info['root_disk'] if root_device['type'] == constants.DISK: root_vhd_path = self._pathutils.lookup_root_vhd_path(instance_name) root_device['path'] = root_vhd_path if not root_vhd_path: base_vhd_path = self._pathutils.get_instance_dir(instance_name) raise exception.DiskNotFound(location=base_vhd_path) ephemerals = block_device_info['ephemerals'] self._check_ephemeral_disks(instance, ephemerals) self._vmops.create_instance(instance, network_info, root_device, block_device_info, vm_gen, image_meta) self._check_and_attach_config_drive(instance, vm_gen) self._vmops.set_boot_order(instance_name, vm_gen, block_device_info) if power_on: self._vmops.power_on(instance, network_info=network_info)
def qemu_img_info(path, format=None): """Return an object containing the parsed output from qemu-img info.""" # TODO(mikal): this code should not be referring to a libvirt specific # flag. # NOTE(sirp): The config option import must go here to avoid an import # cycle CONF.import_opt('images_type', 'nova.virt.libvirt.imagebackend', group='libvirt') if not os.path.exists(path) and CONF.libvirt.images_type != 'rbd': raise exception.DiskNotFound(location=path) try: cmd = ('env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info', path) if format is not None: cmd = cmd + ('-f', format) out, err = utils.execute(*cmd) except processutils.ProcessExecutionError as exp: msg = (_("qemu-img failed to execute on %(path)s : %(exp)s") % { 'path': path, 'exp': exp }) raise exception.InvalidDiskInfo(reason=msg) if not out: msg = (_("Failed to run qemu-img info on %(path)s : %(error)s") % { 'path': path, 'error': err }) raise exception.InvalidDiskInfo(reason=msg) return imageutils.QemuImgInfo(out)
def _extend(): # Get the volume group vg_wrap = self._get_vg_wrap() # Find the disk by name vdisks = vg_wrap.virtual_disks disk_found = None for vdisk in vdisks: # Vdisk name can be either disk_name or /path/to/disk_name if vdisk.name.split('/')[-1] == vol_name.split('/')[-1]: disk_found = vdisk break if not disk_found: LOG.error('Disk %s not found during resize.', vol_name, instance=instance) raise nova_exc.DiskNotFound(location=self.vg_name + '/' + vol_name) self._validate_resizable(disk_found) # Set the new size disk_found.capacity = size # Post it to the VIOS vg_wrap.update()
def get_disk_resource_path(self, connection_info): disk_paths = self._connector.get_volume_paths(connection_info['data']) if not disk_paths: vol_id = connection_info['serial'] err_msg = _("Could not find disk path. Volume id: %s") raise exception.DiskNotFound(err_msg % vol_id) return self._get_disk_res_path(disk_paths[0])
def _check_device_paths(self, device_paths): if len(device_paths) > 1: err_msg = _("Multiple disk paths were found: %s. This can " "occur if multipath is used and MPIO is not " "properly configured, thus not claiming the device " "paths. This issue must be addressed urgently as " "it can lead to data corruption.") raise exception.InvalidDevicePath(err_msg % device_paths) elif not device_paths: err_msg = _("Could not find the physical disk " "path for the requested volume.") raise exception.DiskNotFound(err_msg)
def _get_vmdk_backed_disk_device(self, vm_ref, connection_info_data): # Get the vmdk file name that the VM is pointing to hardware_devices = vm_util.get_hardware_devices(self._session, vm_ref) # Get disk uuid disk_uuid = self._get_volume_uuid(vm_ref, connection_info_data['volume_id']) device = vm_util.get_vmdk_backed_disk_device(hardware_devices, disk_uuid) if not device: raise exception.DiskNotFound(message=_("Unable to find volume")) return device
def privileged_qemu_img_info(path, format=None, output_format=None): """Return an object containing the parsed output from qemu-img info.""" # TODO(mikal): this code should not be referring to a libvirt specific # flag. if not os.path.exists(path) and CONF.libvirt.images_type != 'rbd': raise exception.DiskNotFound(location=path) info = nova.privsep.qemu.privileged_qemu_img_info( path, format=format, qemu_version=QEMU_VERSION, output_format=output_format) if output_format: return imageutils.QemuImgInfo(info, format=output_format) else: return imageutils.QemuImgInfo(info)
def _get_disk_path(self, connection_info): share_addr = self._get_export_path(connection_info) disk_dir = share_addr if self._smbutils.is_local_share(share_addr): share_name = share_addr.lstrip('\\').split('\\')[1] disk_dir = self._smbutils.get_smb_share_path(share_name) if not disk_dir: err_msg = _("Could not find the local share path for %s.") raise exception.DiskNotFound(err_msg % share_addr) disk_name = connection_info['data']['name'] disk_path = os.path.join(disk_dir, disk_name) return disk_path
def unprivileged_qemu_img_info(path, format=None, output_format=None): """Return an object containing the parsed output from qemu-img info.""" try: # The following check is about ploop images that reside within # directories and always have DiskDescriptor.xml file beside them if (os.path.isdir(path) and os.path.exists(os.path.join(path, "DiskDescriptor.xml"))): path = os.path.join(path, "root.hds") cmd = ( 'env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info', path, '--force-share', ) if format is not None: cmd = cmd + ('-f', format) if output_format is not None: cmd = cmd + ("--output=%s" % (output_format), ) out, err = processutils.execute(*cmd, prlimit=QEMU_IMG_LIMITS) except processutils.ProcessExecutionError as exp: if exp.exit_code == -9: # this means we hit prlimits, make the exception more specific msg = (_("qemu-img aborted by prlimits when inspecting " "%(path)s : %(exp)s") % { 'path': path, 'exp': exp }) elif exp.exit_code == 1 and 'No such file or directory' in exp.stderr: # The os.path.exists check above can race so this is a simple # best effort at catching that type of failure and raising a more # specific error. raise exception.DiskNotFound(location=path) else: msg = (_("qemu-img failed to execute on %(path)s : %(exp)s") % { 'path': path, 'exp': exp }) raise exception.InvalidDiskInfo(reason=msg) if not out: msg = (_("Failed to run qemu-img info on %(path)s : %(error)s") % { 'path': path, 'error': err }) raise exception.InvalidDiskInfo(reason=msg) return out
def finish_migration(self, context, migration, instance, disk_info, network_info, image_meta, resize_instance=False, block_device_info=None, power_on=True): LOG.debug("finish_migration called", instance=instance) instance_name = instance.name if self._volumeops.ebs_root_in_block_devices(block_device_info): root_vhd_path = None else: root_vhd_path = self._pathutils.lookup_root_vhd_path(instance_name) if not root_vhd_path: raise exception.DiskNotFound(location=root_vhd_path) root_vhd_info = self._vhdutils.get_vhd_info(root_vhd_path) src_base_disk_path = root_vhd_info.get("ParentPath") if src_base_disk_path: self._check_base_disk(context, instance, root_vhd_path, src_base_disk_path) if resize_instance: new_size = instance.root_gb * units.Gi self._check_resize_vhd(root_vhd_path, root_vhd_info, new_size) eph_vhd_path = self._pathutils.lookup_ephemeral_vhd_path(instance_name) if resize_instance: new_size = instance.get('ephemeral_gb', 0) * units.Gi if not eph_vhd_path: if new_size: eph_vhd_path = self._vmops.create_ephemeral_vhd(instance) else: eph_vhd_info = self._vhdutils.get_vhd_info(eph_vhd_path) self._check_resize_vhd(eph_vhd_path, eph_vhd_info, new_size) vm_gen = self._vmops.get_image_vm_generation(instance.uuid, root_vhd_path, image_meta) self._vmops.create_instance(instance, network_info, block_device_info, root_vhd_path, eph_vhd_path, vm_gen) self._check_and_attach_config_drive(instance, vm_gen) if power_on: self._vmops.power_on(instance)
def finish_migration(self, context, migration, instance, disk_info, network_info, image_meta, resize_instance=False, block_device_info=None, power_on=True): LOG.debug("finish_migration called", instance=instance) instance_name = instance.name vm_gen = self._vmops.get_image_vm_generation(instance.uuid, image_meta) self._block_dev_manager.validate_and_update_bdi( instance, image_meta, vm_gen, block_device_info) root_device = block_device_info['root_disk'] if root_device['type'] == constants.DISK: root_device['path'] = self._pathutils.lookup_root_vhd_path( instance_name) if not root_device['path']: raise exception.DiskNotFound( _("Cannot find boot VHD " "file for instance: %s") % instance_name) root_vhd_info = self._vhdutils.get_vhd_info(root_device['path']) src_base_disk_path = root_vhd_info.get("ParentPath") if src_base_disk_path: self._check_base_disk(context, instance, root_device['path'], src_base_disk_path) if resize_instance: new_size = instance.root_gb * units.Gi self._check_resize_vhd(root_device['path'], root_vhd_info, new_size) ephemerals = block_device_info['ephemerals'] self._check_ephemeral_disks(instance, ephemerals, resize_instance) self._vmops.create_instance(instance, network_info, root_device, block_device_info, vm_gen, image_meta) self._check_and_attach_config_drive(instance, vm_gen) self._vmops.set_boot_order(vm_gen, block_device_info, instance_name) if power_on: self._vmops.power_on(instance)
def _check_ephemeral_disks(self, instance, ephemerals, resize_instance=False): instance_name = instance.name new_eph_gb = instance.get('ephemeral_gb', 0) if len(ephemerals) == 1: # NOTE(claudiub): Resize only if there is one ephemeral. If there # are more than 1, resizing them can be problematic. This behaviour # also exists in the libvirt driver and it has to be addressed in # the future. ephemerals[0]['size'] = new_eph_gb elif sum(eph['size'] for eph in ephemerals) != new_eph_gb: # New ephemeral size is different from the original ephemeral size # and there are multiple ephemerals. LOG.warning(_LW("Cannot resize multiple ephemeral disks for " "instance."), instance=instance) for index, eph in enumerate(ephemerals): eph_name = "eph%s" % index existing_eph_path = self._pathutils.lookup_ephemeral_vhd_path( instance_name, eph_name) if not existing_eph_path: eph['format'] = self._vhdutils.get_best_supported_vhd_format() eph['path'] = self._pathutils.get_ephemeral_vhd_path( instance_name, eph['format'], eph_name) if not resize_instance: # ephemerals should have existed. raise exception.DiskNotFound(location=eph['path']) if eph['size']: # create ephemerals self._vmops.create_ephemeral_disk(instance.name, eph) elif eph['size'] > 0: # ephemerals exist. resize them. eph['path'] = existing_eph_path eph_vhd_info = self._vhdutils.get_vhd_info(eph['path']) self._check_resize_vhd(eph['path'], eph_vhd_info, eph['size'] * units.Gi) else: # ephemeral new size is 0, remove it. self._pathutils.remove(existing_eph_path) eph['path'] = None
def qemu_img_info(path, format=None): """Return an object containing the parsed output from qemu-img info.""" # TODO(mikal): this code should not be referring to a libvirt specific # flag. # NOTE(sirp): The config option import must go here to avoid an import # cycle CONF.import_opt('images_type', 'nova.virt.libvirt.imagebackend', group='libvirt') if not os.path.exists(path) and CONF.libvirt.images_type != 'rbd': msg = (_("Path does not exist %(path)s") % {'path': path}) raise exception.InvalidDiskInfo(reason=msg) cmd = ('env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info', path) if format is not None: cmd = cmd + ('-f', format) try: if QEMU_IMG_LIMITS is not None: out, err = utils.execute(*cmd, prlimit=QEMU_IMG_LIMITS) else: out, err = utils.execute(*cmd) except processutils.ProcessExecutionError as exp: if exp.exit_code == -9: # this means we hit prlimits, make the exception more specific msg = (_("qemu-img aborted by prlimits when inspecting " "%(path)s : %(exp)s") % { 'path': path, 'exp': exp }) elif exp.exit_code == 1 and 'No such file or directory' in exp.stderr: # The os.path.exists check above can race so this is a simple # best effort at catching that type of failure and raising a more # specific error. raise exception.DiskNotFound(location=path) if not out: msg = (_("Failed to run qemu-img info on %(path)s : %(error)s") % { 'path': path, 'error': err }) raise exception.InvalidDiskInfo(reason=msg) return imageutils.QemuImgInfo(out)
def _detach_volume_iscsi(self, connection_info, instance): """Detach volume storage to VM instance.""" vm_ref = vm_util.get_vm_ref(self._session, instance) # Detach Volume from VM LOG.debug("_detach_volume_iscsi: %s", connection_info, instance=instance) data = connection_info['data'] # Discover iSCSI Target device_name, uuid = self._iscsi_get_target(data) if device_name is None: raise exception.StorageError( reason=_("Unable to find iSCSI Target")) # Get the vmdk file name that the VM is pointing to hardware_devices = vm_util.get_hardware_devices(self._session, vm_ref) device = vm_util.get_rdm_disk(hardware_devices, uuid) if device is None: raise exception.DiskNotFound(message=_("Unable to find volume")) self.detach_disk_from_vm(vm_ref, instance, device, destroy_disk=True) LOG.debug("Detached ISCSI: %s", connection_info, instance=instance)
def _check_ephemeral_disks(self, instance, ephemerals, resize_instance=False): instance_name = instance.name new_eph_gb = instance.get('ephemeral_gb', 0) * units.Gi for index, eph in enumerate(ephemerals): eph_name = "eph%s" % index eph['path'] = self._pathutils.lookup_ephemeral_vhd_path( instance_name, eph_name) if not eph['path'] and not resize_instance: raise exception.DiskNotFound( _("Cannot find ephemeral VHD " "file for instance: %s") % instance_name) if resize_instance and not eph['path'] and new_eph_gb: eph['format'] = ( self._vhdutils.get_best_supported_vhd_format()) eph['path'] = self._pathutils.get_ephemeral_vhd_path( instance_name, eph['format'], eph_name) eph['size'] = new_eph_gb self._vmops._create_ephemeral_disk(instance.name, eph)
def _extend(): # Get the volume group vg_wrap = self._get_vg_wrap() # Find the disk by name vdisks = vg_wrap.virtual_disks disk_found = None for vdisk in vdisks: if vdisk.name == vol_name: disk_found = vdisk break if not disk_found: LOG.error(_LE('Disk %s not found during resize.'), vol_name, instance=instance) raise nova_exc.DiskNotFound( location=self.vg_name + '/' + vol_name) # Set the new size disk_found.capacity = size # Post it to the VIOS vg_wrap.update()
def snapshot(self, context, instance, image_href, update_task_state): """ Create sys vol image and upload to glance :param instance: :param image_href: :param update_task_state: :return: """ if not constant.CONF.fusioncompute.fc_image_path: LOG.error(_("config option fc_image_path is None.")) raise fc_exc.InvalidImageDir() # 0.get image service and image id _image_service = glance.get_remote_image_service(context, image_href) snapshot_image_service, image_id = _image_service # 1.import sys vol to nfs dir LOG.info(_("begin uploading sys vol to glance ...")) fc_vm = FC_MGR.get_vm_by_uuid(instance) sys_vol = self._get_sys_vol_from_vm_info(fc_vm) if not sys_vol: raise exception.DiskNotFound(_("can not find sys volume.")) update_task_state(task_state=task_states.IMAGE_PENDING_UPLOAD) self._volume_ops.create_image_from_volume(self.site.volume_uri, sys_vol, image_id) # 2.update image metadata LOG.info(_("begin update image metadata ...")) update_task_state(task_state=task_states.IMAGE_UPLOADING, expected_state=task_states.IMAGE_PENDING_UPLOAD) name = snapshot_image_service.show(context, image_id).get('name') location = self._generate_image_location(image_id) metadata = self._generate_image_metadata(name, location, fc_vm, instance) snapshot_image_service.update(context, image_id, metadata)
def qemu_img_info(path, format=None): """Return an object containing the parsed output from qemu-img info.""" # TODO(mikal): this code should not be referring to a libvirt specific # flag. if not os.path.exists(path) and CONF.libvirt.images_type != 'rbd': raise exception.DiskNotFound(location=path) try: cmd = ('env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info', path) if format is not None: cmd = cmd + ('-f', format) out, err = utils.execute(*cmd, prlimit=QEMU_IMG_LIMITS) except processutils.ProcessExecutionError as exp: msg = (_("qemu-img failed to execute on %(path)s : %(exp)s") % {'path': path, 'exp': exp}) raise exception.InvalidDiskInfo(reason=msg) if not out: msg = (_("Failed to run qemu-img info on %(path)s : %(error)s") % {'path': path, 'error': err}) raise exception.InvalidDiskInfo(reason=msg) return imageutils.QemuImgInfo(out)
def finish_revert_migration(self, context, instance, network_info, block_device_info=None, power_on=True): LOG.debug("finish_revert_migration called", instance=instance) instance_name = instance.name self._revert_migration_files(instance_name) image_meta = self._imagecache.get_image_details(context, instance) vm_gen = self._vmops.get_image_vm_generation(instance.uuid, image_meta) self._block_dev_manager.validate_and_update_bdi( instance, image_meta, vm_gen, block_device_info) root_device = block_device_info['root_disk'] if root_device['type'] == constants.DISK: root_device['path'] = self._pathutils.lookup_root_vhd_path( instance_name) if not root_device['path']: raise exception.DiskNotFound( _("Cannot find boot VHD file for instance: %s") % instance_name) ephemerals = block_device_info['ephemerals'] self._check_ephemeral_disks(instance, ephemerals) self._vmops.create_instance(instance, network_info, root_device, block_device_info, vm_gen, image_meta) self._check_and_attach_config_drive(instance, vm_gen) self._vmops.set_boot_order(vm_gen, block_device_info, instance_name) if power_on: self._vmops.power_on(instance, network_info=network_info)