Ejemplo n.º 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:
            vg_list = volutils.get_all_volume_groups()
            try:
                (vg for vg in vg_list if vg['name'] == dest_vg).next()
            except StopIteration:
                message = (_("Destination Volume Group %s does not exist") %
                           dest_vg)
                LOG.error(message)
                return false_ret

            helper = utils.get_root_helper()
            dest_vg_ref = lvm.LVM(dest_vg, helper,
                                  lvm_type=lvm_type,
                                  executor=self._execute)
            self.remove_export(ctxt, volume)
            self._create_volume(volume['name'],
                                self._sizestr(volume['size']),
                                lvm_type,
                                lvm_mirrors,
                                dest_vg_ref)

            volutils.copy_volume(self.local_path(volume),
                                 self.local_path(volume, vg=dest_vg),
                                 volume['size'],
                                 self.configuration.volume_dd_blocksize,
                                 execute=self._execute)
            self._delete_volume(volume)
            model_update = self._create_export(ctxt, volume, vg=dest_vg)

            return (True, model_update)
        else:
            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.exception(message)
            raise exception.VolumeBackendAPIException(data=message)
Ejemplo n.º 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()
            try:
                self.vg = lvm.LVM(
                    self.configuration.volume_group,
                    root_helper,
                    lvm_type=self.configuration.lvm_type,
                    executor=self._execute,
                )
            except brick_exception.VolumeGroupNotFound:
                message = _("Volume Group %s does not exist") % self.configuration.volume_group
                raise exception.VolumeBackendAPIException(data=message)

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

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

            pool_name = "%s-pool" % self.configuration.volume_group
            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") % exc.stderr
                    raise exception.VolumeBackendAPIException(data=exception_message)
    def check_for_setup_error(self):
        """Verify that requirements are in place to use LVM driver."""

        # [MRA] we will not use this function.
        return
       
        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

            # [MRA] Automatic redundancy control. 
            vgname, phydev = self._create_initial_vg(self.configuration)

            try:
                self.vg = lvm.LVM(self.configuration.volume_group,
                                  root_helper,
                                  create_vg=True,
                                  physical_volumes=phydev,
                                  lvm_type=self.configuration.lvm_type,
                                  executor=self._execute,
                                  lvm_conf=lvm_conf_file)

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

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

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

            pool_name = "%s-pool" % self.configuration.volume_group
            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")
                                         % exc.stderr)
                    raise exception.VolumeBackendAPIException(
                        data=exception_message)
Ejemplo n.º 4
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:
            vg_list = volutils.get_all_volume_groups()
            try:
                (vg for vg in vg_list if vg['name'] == dest_vg).next()
            except StopIteration:
                message = (_("Destination Volume Group %s does not exist") %
                           dest_vg)
                LOG.error(message)
                return false_ret

            helper = utils.get_root_helper()
            dest_vg_ref = lvm.LVM(dest_vg, helper,
                                  lvm_type=lvm_type,
                                  executor=self._execute)
            self.remove_export(ctxt, volume)
            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 = volume['size'] * units.Ki
        volutils.copy_volume(self.local_path(volume),
                             self.local_path(volume, vg=dest_vg),
                             size_in_mb,
                             self.configuration.volume_dd_blocksize,
                             execute=self._execute)
        self._delete_volume(volume)
        model_update = self._create_export(ctxt, volume, vg=dest_vg)

        return (True, model_update)
Ejemplo n.º 5
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:
            vg_list = volutils.get_all_volume_groups()
            try:
                (vg for vg in vg_list if vg['name'] == dest_vg).next()
            except StopIteration:
                message = (_("Destination Volume Group %s does not exist") %
                           dest_vg)
                LOG.error(message)
                return false_ret

            helper = utils.get_root_helper()
            dest_vg_ref = lvm.LVM(dest_vg, helper,
                                  lvm_type=lvm_type,
                                  executor=self._execute)
            self.remove_export(ctxt, volume)
            self._create_volume(volume['name'],
                                self._sizestr(volume['size']),
                                lvm_type,
                                lvm_mirrors,
                                dest_vg_ref)

        volutils.copy_volume(self.local_path(volume),
                             self.local_path(volume, vg=dest_vg),
                             volume['size'],
                             self.configuration.volume_dd_blocksize,
                             execute=self._execute)
        self._delete_volume(volume)
        model_update = self._create_export(ctxt, volume, vg=dest_vg)

        return (True, model_update)
Ejemplo n.º 6
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:
            vg_list = volutils.get_all_volume_groups()
            try:
                next(vg for vg in vg_list if vg['name'] == dest_vg)
            except StopIteration:
                LOG.error(_LE("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
Ejemplo n.º 7
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:
                self.vg = lvm.LVM(self.configuration.volume_group,
                                  root_helper,
                                  lvm_type=self.configuration.lvm_type,
                                  executor=self._execute,
                                  lvm_conf=lvm_conf_file)

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

        vg_list = volutils.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)

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

            pool_name = "%s-pool" % self.configuration.volume_group
            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
Ejemplo n.º 8
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:
                self.vg = lvm.LVM(self.configuration.volume_group,
                                  root_helper,
                                  lvm_type=self.configuration.lvm_type,
                                  executor=self._execute,
                                  lvm_conf=lvm_conf_file)

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

        vg_list = volutils.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)

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

            pool_name = "%s-pool" % self.configuration.volume_group
            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
Ejemplo n.º 9
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(':')
        except ValueError:
            return false_ret
        if (dest_type != 'LVMVolumeDriver' or dest_hostname != self.hostname):
            return false_ret

        if dest_vg != self.vg.vg_name:
            vg_list = volutils.get_all_volume_groups()
            vg_dict = \
                (vg for vg in vg_list if vg['name'] == self.vg.vg_name).next()
            if vg_dict is None:
                message = ("Destination Volume Group %s does not exist" %
                           dest_vg)
                LOG.error(_('%s'), message)
                return false_ret

            helper = utils.get_root_helper()
            dest_vg_ref = lvm.LVM(dest_vg, helper, lvm_type, self._execute)
            self.remove_export(ctxt, volume)
            self._create_volume(volume['name'],
                                self._sizestr(volume['size']),
                                lvm_type,
                                lvm_mirrors,
                                dest_vg_ref)

        volutils.copy_volume(self.local_path(volume),
                             self.local_path(volume, vg=dest_vg),
                             volume['size'],
                             execute=self._execute)
        self._delete_volume(volume)
        model_update = self._create_export(ctxt, volume, vg=dest_vg)

        return (True, model_update)
Ejemplo n.º 10
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 '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(':')
        except ValueError:
            return false_ret
        if (dest_type != 'LVMVolumeDriver' or dest_hostname != self.hostname):
            return false_ret

        if dest_vg != self.vg.vg_name:
            vg_list = volutils.get_all_volume_groups()
            vg_dict = \
                (vg for vg in vg_list if vg['name'] == self.vg.vg_name).next()
            if vg_dict is None:
                message = ("Destination Volume Group %s does not exist" %
                           dest_vg)
                LOG.error(_('%s'), message)
                return false_ret

            helper = 'sudo cinder-rootwrap %s' % CONF.rootwrap_config
            dest_vg_ref = lvm.LVM(dest_vg, helper, lvm_type, self._execute)
            self.remove_export(ctxt, volume)
            self._create_volume(volume['name'],
                                self._sizestr(volume['size']),
                                lvm_type,
                                lvm_mirrors,
                                dest_vg_ref)

        volutils.copy_volume(self.local_path(volume),
                             self.local_path(volume, vg=dest_vg),
                             volume['size'],
                             execute=self._execute)
        self._delete_volume(volume)
        model_update = self._create_export(ctxt, volume, vg=dest_vg)

        return (True, model_update)
Ejemplo n.º 11
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:
            vg_list = volutils.get_all_volume_groups()
            try:
                (vg for vg in vg_list if vg["name"] == dest_vg).next()
            except StopIteration:
                message = "Destination Volume Group %s does not exist" % dest_vg
                LOG.error(_("%s"), message)
                return false_ret

            helper = utils.get_root_helper()
            dest_vg_ref = lvm.LVM(dest_vg, helper, lvm_type=lvm_type, executor=self._execute)
            self.remove_export(ctxt, volume)
            self._create_volume(volume["name"], self._sizestr(volume["size"]), lvm_type, lvm_mirrors, dest_vg_ref)

        volutils.copy_volume(
            self.local_path(volume),
            self.local_path(volume, vg=dest_vg),
            volume["size"],
            self.configuration.volume_dd_blocksize,
            execute=self._execute,
        )
        self._delete_volume(volume)
        model_update = self._create_export(ctxt, volume, vg=dest_vg)

        return (True, model_update)
Ejemplo n.º 12
0
    def check_for_setup_error(self):
        """Verify that requirements are in place to use LVM driver."""
        if self.vg is None:
            root_helper = 'sudo cinder-rootwrap %s' % CONF.rootwrap_config
            try:
                self.vg = lvm.LVM(self.configuration.volume_group,
                                  root_helper,
                                  lvm_type=self.configuration.lvm_type,
                                  executor=self._execute)
            except lvm.VolumeGroupNotFound:
                message = ("Volume Group %s does not exist" %
                           self.configuration.volume_group)
                raise exception.VolumeBackendAPIException(data=message)

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

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

            pool_name = "%s-pool" % self.configuration.volume_group
            if self.vg.get_volume(pool_name) is None:
                try:
                    self.vg.create_thin_pool(pool_name)
                except exception.ProcessExecutionError as exc:
                    exception_message = ("Failed to create thin pool, "
                                         "error message was: %s"
                                         % exc.stderr)
                    raise exception.VolumeBackendAPIException(
                        data=exception_message)
Ejemplo n.º 13
0
 def test_get_all_volume_groups(self, mock_get_groups, mock_helper):
     self.assertEqual(mock_get_groups.return_value,
                      volume_utils.get_all_volume_groups())
     mock_helper.assert_called_once_with()
Ejemplo n.º 14
0
 def test_get_all_volume_groups(self, mock_get_groups, mock_helper):
     self.assertEqual(mock_get_groups.return_value,
                      volume_utils.get_all_volume_groups())
     mock_helper.assert_called_once_with()
Ejemplo n.º 15
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 = volutils.get_all_volume_groups()
        try:
            next(vg for vg in vg_list if vg['name'] == dest_vg)
        except StopIteration:
            LOG.error(_LE("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:
            volutils.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(_LE("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)
Ejemplo n.º 16
0
Archivo: lvm.py Proyecto: NetApp/cinder
    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 = volutils.get_all_volume_groups()
        try:
            next(vg for vg in vg_list if vg['name'] == dest_vg)
        except StopIteration:
            LOG.error(_LE("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:
            volutils.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(_LE("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)
Ejemplo n.º 17
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:
                self.vg = lvm.LVM(
                    self.configuration.volume_group,
                    root_helper,
                    lvm_type=self.configuration.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 = volutils.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 volutils.supports_thin_provisioning():
                if self.vg.get_volume(pool_name) is not None:
                    LOG.info(_LI('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(_LI('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 volutils.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