跳转到: 导航, 搜索

指定/蓝图/批量操作

概述

用户应该能够创建、修改和删除多个资源。

一次应用多个操作有很多用例。例如

  • 多个区域的区域级 TTL 可能需要更新以进行迁移。
  • 帐户/租户清理正在进行中,需要清除区域。https://wiki.openstack.org/w/index.php?title=Designate/Blueprints/Bulk_Actions&action=edit&section=1
  • 新用户快速添加所有区域。

阶段 1:使数据库交互更具事务性

与存储的数据库交互应该以以下方式进行

  1. 开始事务
  2. 执行适当的数据操作以完成当前任务(例如,创建区域)
  3. 如果没有发生错误,则提交事务并结束它
  4. 如果发生错误,则回滚事务并结束它


SQLAlchemy 支持事务 通过会话,因此 SQLAlchemy 驱动程序需要更新以使用这些操作。

这包括

   def begin(self):
       self.session.begin(subtransactions=True)
   def commit(self):
      self.session.commit()
   def rollback(self):
      self.session.rollback()

designate/storage/api.py 中调用,使用 "self.storage.begin()"。由于会话本身已经属于一个事务,因此必须在 begin() 中使用子事务。

这将允许通过利用 SQLAlchemy 内置的回滚功能来消除 storage/api.py 中的手动回滚。例如

   @contextlib.contextmanager
   def create_domain(self, context, values):
       domain = self.storage.create_domain(context, values)
       try:
           yield domain
       except Exception:
           with excutils.save_and_reraise_exception():
               self.storage.delete_domain(context, domain['id'])

将更改为

   @contextlib.contextmanager
   def create_domain(self, context, values):
       self.storage.begin()
       domain = self.storage.create_domain(context, values)
       try:
           yield domain
       except Exception:
           with excutils.save_and_reraise_exception():
               self.storage.rollback()
       else:
           self.storage.commit()


阶段 2:支持批量操作

注意:这需要进一步完善和讨论。

可以通过几种不同的方式来完成。

以下是 API 调用可能呈现的几种不同方式。这方面有几乎无限的可能性,需要进行讨论。

http://xx.xx.x.x:9001/v2/zones POST

{
  "zone": {
    "name": "example.org.",
    "email": "joe@example.org",
    "ttl": 7200
  },
  "zone": {
    "name": "example2.org.",
    "email": "joe@example.org",
    "ttl": 7200
  }
} 
OR
{
   "zones": {
       "email": "joe@example.org",
       "ttl": 7200,
       "names": [
           {
               "name": "example.org."
           },
           {
               "name": "example2.org."
           }
       ]
   }
} 
OR
{
     example.org
     example2.org
}


其中一些操作无疑会有自己的蓝图等等,但这两个选项只是实现批量操作的两种思路。

选项 1

扩展新的事务,逐个调用。

因此,无论 API 调用的实现如何,批量操作的方法都会逐个调用单个操作的方法,并报告操作的结果。这本质上等同于编写一个执行所需批量操作的脚本。

该选项允许某些请求成功,而某些请求失败。这将被报告给用户。然后由他们来修复导致它们失败的任何问题,或者如果这是 Designate 的错误,则重试。

该方法本质上是通过编写使用客户端或 API 的脚本来实现的。

选项 2

“全有或全无”的方法。

将尝试应用批量操作,但如果任何部分失败,则整个操作无效,并且所有内容都将回滚。

如果失败,将向用户传递错误消息,告知他们具体失败的内容,他们可以重试或重新考虑。

该选项可防止用户进入他们不希望的状态。在此场景中,用户永远不会尝试添加 100 个区域并最终添加 77 个区域。它最大限度地减少了因某些事情失败而导致更改许多事情但未实现用户原始意图的风险。