Beispiel #1
0
    def migrate_volume(self, ctxt, volume, host, thin=False, mirror_count=0):
        """Optimize the migration if the destination is on the same server.

        If the specified host is another back-end on the same server, and
        the volume is not attached, we can do the migration locally without
        going through iSCSI.
        """

        false_ret = (False, None)
        if volume['status'] != 'available':
            return false_ret
        if 'location_info' not in host['capabilities']:
            return false_ret
        info = host['capabilities']['location_info']
        try:
            (dest_type, dest_hostname, dest_vg, lvm_type, lvm_mirrors) =\
                info.split(':')
            lvm_mirrors = int(lvm_mirrors)
        except ValueError:
            return false_ret
        if (dest_type != 'LVMVolumeDriver' or dest_hostname != self.hostname):
            return false_ret

        if dest_vg == self.vg.vg_name:
            message = (_("Refusing to migrate volume ID: %(id)s. Please "
                         "check your configuration because source and "
                         "destination are the same Volume Group: %(name)s.") %
                       {
                           'id': volume['id'],
                           'name': self.vg.vg_name
                       })
            LOG.error(message)
            raise exception.VolumeBackendAPIException(data=message)

        vg_list = volume_utils.get_all_volume_groups()
        try:
            next(vg for vg in vg_list if vg['name'] == dest_vg)
        except StopIteration:
            LOG.error("Destination Volume Group %s does not exist", dest_vg)
            return false_ret

        helper = utils.get_root_helper()

        lvm_conf_file = self.configuration.lvm_conf_file
        if lvm_conf_file.lower() == 'none':
            lvm_conf_file = None

        dest_vg_ref = lvm.LVM(dest_vg,
                              helper,
                              lvm_type=lvm_type,
                              executor=self._execute,
                              lvm_conf=lvm_conf_file)

        self._create_volume(volume['name'], self._sizestr(volume['size']),
                            lvm_type, lvm_mirrors, dest_vg_ref)
        # copy_volume expects sizes in MiB, we store integer GiB
        # be sure to convert before passing in
        size_in_mb = int(volume['size']) * units.Ki
        try:
            volume_utils.copy_volume(self.local_path(volume),
                                     self.local_path(volume, vg=dest_vg),
                                     size_in_mb,
                                     self.configuration.volume_dd_blocksize,
                                     execute=self._execute,
                                     sparse=self._sparse_copy_volume)
        except Exception as e:
            with excutils.save_and_reraise_exception():
                LOG.error(
                    "Volume migration failed due to "
                    "exception: %(reason)s.", {'reason': six.text_type(e)},
                    resource=volume)
                dest_vg_ref.delete(volume)
        self._delete_volume(volume)
        return (True, None)
Beispiel #2
0
    def check_for_setup_error(self):
        """Verify that requirements are in place to use LVM driver."""
        if self.vg is None:
            root_helper = utils.get_root_helper()

            lvm_conf_file = self.configuration.lvm_conf_file
            if lvm_conf_file.lower() == 'none':
                lvm_conf_file = None

            try:
                lvm_type = self.configuration.lvm_type
                if lvm_type == 'auto':
                    if volume_utils.supports_thin_provisioning():
                        lvm_type = 'thin'
                    else:
                        lvm_type = 'default'
                self.vg = lvm.LVM(
                    self.configuration.volume_group,
                    root_helper,
                    lvm_type=lvm_type,
                    executor=self._execute,
                    lvm_conf=lvm_conf_file,
                    suppress_fd_warn=(
                        self.configuration.lvm_suppress_fd_warnings))

            except exception.VolumeGroupNotFound:
                message = (_("Volume Group %s does not exist") %
                           self.configuration.volume_group)
                raise exception.VolumeBackendAPIException(data=message)

        vg_list = volume_utils.get_all_volume_groups(
            self.configuration.volume_group)
        vg_dict = next(vg for vg in vg_list if vg['name'] == self.vg.vg_name)
        if vg_dict is None:
            message = (_("Volume Group %s does not exist") %
                       self.configuration.volume_group)
            raise exception.VolumeBackendAPIException(data=message)

        pool_name = "%s-pool" % self.configuration.volume_group

        if self.configuration.lvm_type == 'auto':
            # Default to thin provisioning if it is supported and
            # the volume group is empty, or contains a thin pool
            # for us to use.
            self.vg.update_volume_group_info()

            self.configuration.lvm_type = 'default'

            if volume_utils.supports_thin_provisioning():
                if self.vg.get_volume(pool_name) is not None:
                    LOG.info('Enabling LVM thin provisioning by default '
                             'because a thin pool exists.')
                    self.configuration.lvm_type = 'thin'
                elif len(self.vg.get_volumes()) == 0:
                    LOG.info('Enabling LVM thin provisioning by default '
                             'because no LVs exist.')
                    self.configuration.lvm_type = 'thin'

        if self.configuration.lvm_type == 'thin':
            # Specific checks for using Thin provisioned LV's
            if not volume_utils.supports_thin_provisioning():
                message = _("Thin provisioning not supported "
                            "on this version of LVM.")
                raise exception.VolumeBackendAPIException(data=message)

            if self.vg.get_volume(pool_name) is None:
                try:
                    self.vg.create_thin_pool(pool_name)
                except processutils.ProcessExecutionError as exc:
                    exception_message = (_("Failed to create thin pool, "
                                           "error message was: %s") %
                                         six.text_type(exc.stderr))
                    raise exception.VolumeBackendAPIException(
                        data=exception_message)

            # Enable sparse copy since lvm_type is 'thin'
            self._sparse_copy_volume = True