通用卷组

https://blueprints.launchpad.net/cinder/+spec/generic-volume-group

在本规范中,我们设计了一个通用的卷组。通用卷组可以被驱动程序用于各种目的,并且未来可以轻松扩展以添加新功能。

问题描述

在 Cinder 中,目前可用的唯一组构造是一致性组。一致性组今天仅支持一致性组快照。当我们开始考虑扩展此支持以进行组复制时,出现了很多问题。一致性组意味着数据一致性。对于某些驱动程序,组复制可以确保组中卷之间的数据一致性,但对于其他驱动程序,组复制并不意味着数据一致性。

在本规范中,我们设计了一个通用的卷组。此组构造可以为添加组复制支持奠定基础,该支持将在不同的规范中讨论。添加通用卷组的原因是它可以被驱动程序用于不同的目的。在本规范中,我们将提供基本功能,包括创建、删除和更新卷组。一旦添加了基本的通用卷组,我们就可以轻松地扩展它以支持更多新功能,而无需添加复杂的新的 API。

在下一节中,添加了用例来解释为什么需要组构造。

用例

  • 将卷组合在一起以实现共同目的。租户可能希望将用于同一应用程序的卷组合在一个组中,以便更容易地一起管理它们。

  • 组复制。在之前的规范评审中,建议将通用卷组与组复制分开,并在单独的规范中涵盖。正如建议的那样,组复制在 [1] 中的单独规范中详细讨论。

    一旦可用卷组构造,它就为添加组复制支持奠定了基础。 [1] 中提出的复制功能仅适用于具有 group_replication_enabled 或 consistent_group_replication_enabled 规范设置为 True 的组。这意味着,如果您创建了一个没有 group_replication_enabled 或 consistent_group_replication_enabled 规范设置为 True 的组,则无法在该组上启用复制。

  • 组快照。 组快照的详细信息在另一个规范 [2] 中讨论。 一旦可用卷组构造,它就为添加组快照支持奠定了基础。 我们还需要更改现有的 Consistency Group 快照 API 以采用新的组构造,并确保它不会破坏滚动升级。

    [2] 中提出的组快照与今天现有的 cgsnapshot 之间存在差异。 组快照支持两种功能,即 consistent_group_snapshot_enabled 和 group_snapshot_enabled。 具有 consistent_group_snapshot_enabled 规范设置为 True 的组快照等效于今天现有的 cgsnapshot。 具有 group_snapshot_enabled 规范设置为 True 的组快照是一组快照,不保证存储级别的一致性。 更多详细信息请参见 [2]。

    现有工作流程:1. consisgroup-create 创建一个 CG,它是一组卷。 一些驱动程序调用数组 API 将卷放入数组中的一个组中,以便以后可以获取一致的快照,但其他驱动程序实际上在此步骤中没有数组 API,因此 Cinder 只是将卷放入数据库中的一个组中。 下一个命令 cgsnapshot-create 是保证时间点一致性的命令。 2. cgsnapshot-create 创建一个 CG 快照,即一致性组快照。

    新工作流程:1. group-create 2. group-snapshot-create 组快照的一致性与否取决于组类型和驱动程序报告的功能。

提议的变更

  • 创建组

    • 添加一个 API,允许租户创建卷组。

    • 相应地添加卷驱动程序 API。

  • 删除组

    • 添加一个 API,允许租户删除卷组。

    • 相应地添加卷驱动程序 API。

  • 列出组

    • 添加一个 API 来列出卷组。

  • 显示组

    • 添加一个 API 来显示卷组。

  • 更新组

    • 添加一个 API,用于在创建后将现有卷添加到组中,并从组中删除卷。

    • 相应地添加卷驱动程序 API。

    • 注意:这是将现有卷添加到组或从组中删除卷而不删除它的能力。 一些驱动程序维护人员报告说,他们的驱动程序不支持更新组。 例如,HNAS iSCSI 驱动程序在实现现有的 CG 功能时无法支持更新组,因为它意味着在文件系统之间移动文件,并且它还没有 API 来执行此操作 [3]。 在实施更新组时,驱动程序维护人员应评估后端功能并检查组类型规范,以确定是否可以支持它。

  • 组类型

    • 像卷的卷类型一样,为组添加一个组类型。

    • 一个组只能支持一种组类型。

  • 组类型规范

    • 添加组类型规范来描述组的特征,就像卷类型对卷类型的额外规范一样。

    • 组类型规范将报告为类似于卷类型额外规范的“capabilities”。

  • 调度器中的更改。

    • 对调度器进行更改,以便选择合适的后端来创建组。

  • 数据库模式更改

    • 将创建一个新的 group_type 表,其中包含以下内容:* group_type 的 uuid * 名称 * 描述

    • 将创建一个新的 group_type_specs 表。

      • 规范的 uuid

      • value

      • group_type 的 uuid 作为外键

    • 将创建一个新的 group 表,其中包含以下内容

      • 组的 uuid

      • group_type 的 uuid 作为外键

      • name

      • description

    • 将创建一个新的 volume_group_mapping 表,其中包含以下列。 这是必需的,因为一个卷可以位于多个组中。

      • 映射条目的 uuid

      • 卷的 uuid

      • 组的 uuid

      • 注意:将卷限制为仅一个组将限制我们未来对通用组构造所能做的事情。

    • 将创建一个新的 group_volumetypes_mapping 表,其中包含 3 列

      • group_volumetype 条目的 uuid

      • 组的 uuid

      • 卷类型 uuid

    • 将添加一个组配额机制,类似于我们对 CG 所做的。

  • 将进行更改以确保新的组构造可以支持 CG。

    • 在 Newton 版本中,我们应该能够使用新的 API 创建 CG,并保留 CG API 的现有行为。

    • 在 Ocata 版本中,组将在新表和旧表中创建,我们将从旧表读取。

    • 在“P”版本中,我们将写入新表和旧表,并从新表读取。

    • 在“Q”版本中,将删除旧表。 写入和读取都将从新表进行。

  • 驱动程序需要报告组功能。 示例如下

    • consistent_group_replication_enabled

    • group_replication_enabled

    • consistent_group_snapshot_enabled

    • group_snapshot_enabled

    组类型规范需要指定功能,即 {‘group_snapshot_enabled’: <is> True}

备选方案

如果没有这些提议的更改,我们可以将复制支持添加到现有的 Consistency Group,但将不会拥有可以服务更多用途的通用卷组。

数据模型影响

  • 数据库模式更改

    • 将创建一个新的 group_type 表,其中包含以下内容

      • group_type 的 uuid

      • name

      • description

    • 将创建一个新的 group 表,其中包含以下内容

      • 组的 uuid

      • group_type 的 uuid 作为外键

      • name

      • description

    • 将创建一个新的 group_specs 表,其中包含以下内容

      • group_spec 的 uuid

      • value

      • group_type 的 uuid 作为外键

    • 将创建一个新的 group_volumetypes 表,其中包含 3 列

      • group_volumetype 条目的 uuid

      • 组的 uuid

      • 卷类型 uuid

    • 卷表将有一列

      • 组的 uuid 作为外键

REST API 影响

新的组类型 API

  • 创建组类型

    • V3/<管理员的租户 ID>/group_types

    • 方法:POST

    • V3 的 JSON 模式定义

      {
          "group_type":
          {
              "name": "my_group_type",
              "description": "My group type",
              "group_type_specs": {"key1": "value1", "key2": "value2", ...}
          }
      }
      
  • 删除组类型

    • V3/<管理员的租户 ID>/group_types/<group_type_uuid>

    • 方法:DELETE

    • 此 API 没有正文。

新的组类型规范 API

  • 创建组类型规范

    • V3/<管理员的租户 ID>/group_types/<group_type_uuid>/group_type_specs

    • 方法:POST

    • V3 的 JSON 模式定义

      {
          "group_type_specs":
          {
              "key": "value"
          }
      }
      
  • 删除组类型规范

    • V3/<管理员的租户 ID>/group_types/<group_type_uuid>/group_type_specs/ <spec_uuid>

    • 方法:DELETE

    • 此 API 没有正文。

  • 列出组类型规范

    • V3/<管理员的租户 ID>/group_types/<group_type_uuid>/group_type_specs

    • 方法:GET

    • 此 API 没有正文。

  • 显示组类型规范

    • V3/<管理员的租户 ID>/group_types/<group_type_uuid>/group_type_specs/ <spec_uuid>

    • 方法:GET

    • 此 API 没有正文。

新的组 API

  • 创建组

    • V3/<租户 ID>/groups

    • 方法:POST

    • V3 的 JSON 模式定义

      {
          "group":
          {
              "name": "my_group",
              "description": "My group",
              "group_type": group_type_uuid,
              "volume_types": [volume_type1_uuid, volume_type2_uuid, ...],
              "availability_zone": "az1"
          }
      }
      
    • Cinder 调度器将找到支持组类型和卷类型的后端。 一个组将托管在一个后端上,类似于 CG。 首先使用上述 API 创建一个空组。 创建组后,租户可以创建一个卷,提供组 uuid 和卷类型,该卷将被置备并放置在组和驻留组的后端上。

    • 包含卷类型的原因是在组被选中放置的后端将能够在以后托管指定卷类型。

    • 一个组可以支持一种组类型和多种卷类型。

    • Cinder API 将负责在数据库中创建组条目。 Cinder 驱动程序可能不需要在首次创建空组时执行任何特殊操作。 大多数驱动程序只需要返回成功。

  • 更新组

    • V3/<租户 ID>/groups/<group uuid>

    • 方法:PUT

    • V3 的 JSON 模式定义

      {
          "group":
          {
              "name": "my_group",
              "description": "My group",
              "add_volumes": [volume uuid 1, volume uuid 2,...]
              "remove_volumes": [volume uuid 8, volume uuid 9,...]
          }
      }
      
    • 此方法可以更新名称、描述以及组中的卷。 “add_volumes”之后列表将包含要添加到组的卷的 UUID,而“remove_volumes”之后的列表将包含要从组中删除的卷的 UUID。 API 将验证输入名称、描述、add_volumes 和 remove_volumes 字段中的 UUID 是否与 Cinder db 中的信息一致,并将请求发送到卷管理器。 管理器将调用驱动程序在后端上执行更新。 API 将更新 Cinder db。

  • 删除组

    • V3/<租户 ID>/groups/<group uuid>/action

    • 方法:POST(我们需要使用“POST”而不是“DELETE”在这里,因为请求正文包含一个标志,因此不为空。)

    • V3 的 JSON 模式定义

      {
          "delete":
          {
              "delete-volumes": False
          }
      }
      
    • 将 delete-volumes 标志设置为 True 以删除包含卷的组。 这将删除该组和所有卷。 删除空组不需要将标志设置为 True。

  • 列出组

    • V3/<租户 ID>/groups

    • 此 API 列出所有组的摘要信息。

    • 方法:GET

    • 此 API 没有正文。

  • 列出组(详细)

    • V3/<租户 ID>/groups/detail

    • 此 API 列出所有组的详细信息。

    • 方法:GET

    • 此 API 没有正文。

  • 显示组

    • V3/<租户 ID>/groups/<group uuid>

    • 方法:GET

    • 此 API 没有正文。

  • 更改创建卷 API

    • 将在请求正文中添加一个新字段“group_id”(组的 uuid)。

  • Cinder 卷驱动程序 API

    将添加以下新的卷驱动程序 API

    • def create_group(self, context, group)

    • def update_group(self, context, group, add_volumes=None, remove_volumes=None)

    • def delete_group(self, context, group, volumes)

安全影响

无。

通知影响

将添加创建、删除和更新组的通知。

其他最终用户影响

需要更改 python-cinderclient 以支持新的 API。

  • 创建组类型

    cinder group-type-create –description <description> <name>

  • 删除组类型

    cinder group-type-delete <group type uuid>

  • 显示组类型

    cinder group-type-show <group type uuid>

  • 列出组类型

    cinder group-type-list

  • 设置/取消设置组类型规范

    cinder group-type-key <group type name or uuid> <action> <key-value> 有效操作是“set”或“unset”。

  • 列出组类型规范

    cinder group-type-specs-list

  • 创建组

    cinder group-create –name <name> –description <description> –availability-zone <availability-zone> –volume-types <volume type uuid> [<volume type uuid>…] group_type

  • 更新组

    cinder group-update –name <new name> –description <new description> –add-volumes <volume uuid> [<volume uuid> …] –remove-volumes <volume uuid> [<volume uuid> …] <group uuid or name>

  • 删除组

    cinder group-delete –delete-volumes <group uuid> [<group uuid> …] 如果组不为空,则需要 delete-volumes 标志。

  • 列出组

    cinder group-list

  • 显示组

    cinder group-show <group uuid>

性能影响

其他部署者影响

开发人员影响

驱动程序开发人员可以实施新的驱动程序 API。

实现

负责人

主要负责人

xing-yang

其他贡献者

工作项

  1. 新的组类型 API

    • 创建组类型

    • 删除组类型

  2. 新的组类型规范 API

    • 创建组类型规范

    • 删除组类型规范

    • 列出组类型规范

    • 显示组类型规范

  3. 新的组 API

    • 创建组

    • 更新组

    • 删除组

    • 列出组

    • 显示组

  4. 新的卷驱动程序 API 更改

    • 创建组

    • 更新组

    • 删除组

  5. 数据库模式更改

  6. 在 LVM 驱动程序中实施组方法。

  7. 确保新的和旧的组 API 都能工作。 请参阅规范 [2] 中有关如何实现此目标的详细信息。

依赖项

测试

将添加新的单元测试来测试更改后的代码。

文档影响

需要进行文档更改。

参考资料

[1] 复制组规范

https://review.openstack.org/#/c/229722/

[2] 组快照规范

https://review.openstack.org/#/c/331397/

[3] HNAS iSCSI 驱动程序一致性组支持代码审查

https://review.openstack.org/#/c/327043/4/cinder/volume/drivers/ hitachi/hnas_iscsi.py@939