本作品采用知识共享署名 3.0 非移植许可协议授权。 http://creativecommons.org/licenses/by/3.0/legalcode

异步区域导入/导出

https://blueprints.launchpad.net/designate/+spec/async-import-export

问题描述

大型区域导入可能需要比通常允许的 API 响应时间更长。解析大型区域文件以及插入必要的记录数量与需要导入的记录数量成线性关系。

提议的变更

区域导入的 API 需要更改为异步。这将涉及一个新的数据库表用于区域导入“状态”,以及一个更强大的系统来管理区域数据的解析和插入。区域导出也将回归 v2 API。

API 变更

GET /v2/zones/tasks/imports

这允许用户查看他们的区域导入请求的状态。如果导入已成功完成,他们可以获取区域 ID 和指向区域的链接。

GET /v2/zones/tasks/import/cddda8f0-f558-11e3-a3ac-0800200c9a66 HTTP/1.1
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Location: /v2/zones/tasks/import/cddda8f0-f558-11e3-a3ac-0800200c9a66

{
  "imports": [
      {
        "id": "cddda8f0-f558-11e3-a3ac-0800200c9a66",
        "zone_id": "agqm44f0-s638-15e3-f4d3-1893572c9a67",
        "status": "SUCCESS",
        "links":{
            "self": "http://127.0.0.1:9001/v2/zones/tasks/import/cddda8f0-f558-11e3-a3ac-0800200c9a66",
            "href": "http://127.0.0.1:9001/v2/zones/agqm44f0-s638-15e3-f4d3-1893572c9a67"
      },
      {
        "id": "addda8f0-f558-11e3-a3ac-0800200c9a66",
        "zone_id": "qgqm44f0-s638-15e3-f4d3-1893572c9a67",
        "status": "SUCCESS",
        "links":{
            "self": "http://127.0.0.1:9001/v2/zones/tasks/import/addda8f0-f558-11e3-a3ac-0800200c9a66",
            "href": "http://127.0.0.1:9001/v2/zones/qgqm44f0-s638-15e3-f4d3-1893572c9a67"
      }
  ]
}

POST /v2/zones/tasks/imports

这将创建一个请求以导入一个区域。区域数据通过请求体传递,并且 Content-Type 标头必须设置为 ‘text/dns’。

这将返回一个导入请求的 ID,供用户查询。

POST /v2/zones/tasks/import HTTP/1.1
Accept: application/json
Content-Type: text/dns

$ORIGIN example.com.
example.com. 42 IN SOA ns.example.com. nsadmin.example.com. 42 42 42 42 42
example.com. 42 IN NS ns.example.com.
example.com. 42 IN MX 10 mail.example.com.
ns.example.com. 42 IN A 10.0.0.1
mail.example.com. 42 IN A 10.0.0.2

HTTP/1.1 201 Accepted
Content-Type: application/json; charset=UTF-8
Location: /v2/zones/tasks/import/cddda8f0-f558-11e3-a3ac-0800200c9a66

{
    "id": "cddda8f0-f558-11e3-a3ac-0800200c9a66",
    "zone_id": null,
    "status": "PENDING",
    "links":{
        "self": "http://127.0.0.1:9001/v2/zones/tasks/import/cddda8f0-f558-11e3-a3ac-0800200c9a66"
    }
}

GET /v2/zones/tasks/imports/<id>

这允许用户查看他们的区域导入请求的状态。如果导入已成功完成,他们可以获取区域 ID 和指向区域的链接。

GET /v2/zones/tasks/import/cddda8f0-f558-11e3-a3ac-0800200c9a66 HTTP/1.1
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Location: /v2/zones/tasks/import/cddda8f0-f558-11e3-a3ac-0800200c9a66

{
    "id": "cddda8f0-f558-11e3-a3ac-0800200c9a66",
    "zone_id": "agqm44f0-s638-15e3-f4d3-1893572c9a67",
    "status": "SUCCESS",
    "links":{
        "self": "http://127.0.0.1:9001/v2/zones/tasks/import/cddda8f0-f558-11e3-a3ac-0800200c9a66",
        "href": "http://127.0.0.1:9001/v2/zones/agqm44f0-s638-15e3-f4d3-1893572c9a67"
    }
}

GET /v2/zones/<id>

此请求,带有标头 “Accept:text/dns” 以 DNS 区域文件格式向用户导出区域。

GET /v2/zones/cddda8f0-f558-11e3-a3ac-0800200c9a66 HTTP/1.1
Accept: text/dns

HTTP/1.1 200 OK
Content-Type: text/dns; charset=UTF-8
Location: /v2/zones/cddda8f0-f558-11e3-a3ac-0800200c9a66

HTTP/1.1 200 OK
Content-Type: text/dns

$ORIGIN example.com.
$TTL 42
example.com. IN SOA ns.designate.com. nsadmin.example.com. (
    1394213803 ; serial
    3600 ; refresh
    600 ; retry
    86400 ; expire
    3600 ; minimum
)
example.com. IN NS ns.designate.com.
example.com.  IN MX 10 mail.example.com.
ns.example.com.  IN A  10.0.0.1
mail.example.com.  IN A  10.0.0.2

Central 变更

create_import_domain(body)

参数

描述

必需

body

来自 API 请求的未序列化请求数据

1. 在 zone_imports 表中创建一个条目以跟踪请求,状态为 PENDING。 2. 启动一个线程来使用请求体执行 _import_domain。 3. 返回一个 zone_import 对象。

get_import_domain(id)

参数

描述

必需

import_id

区域导入的 ID

1. 调用 storage.find_import 以从 zone_imports 表中获取特定的 zone_import 记录。 2. 返回 zone_import 对象

find_import_domains(context)

参数

描述

必需

context

要传递给 storage.find_imports 的上下文

1. 调用 storage.find_imports 以查找租户的所有区域导入。 2. 返回 zone_import_list 对象

delete_import_domain(id)

参数

描述

必需

import_id

区域导入的 ID

1. 调用 storage.delete_zone_import 以从 zone_imports 表中删除区域导入记录。

_import_domain(body)

参数

描述

必需

body

来自 API 请求的未序列化请求数据

zone_import

来自原始请求的 zone_import 对象

1. 尝试使用 dnspython 的 from_text 方法将区域转换为 dnspython 对象。如果不起作用,则更新存储中的 zone_import 对象为 ERROR,以指示无法导入区域。 2. 将 dnspython 区域转换为 Designate 域对象。 3. 调用 central.create_domain 并使用转换后的对象。 4. 获取返回对象的 ID,并使用新的 zone_id 更新存储中的 zone_import 对象,并将导入状态更新为 COMPLETE 或类似状态。

Storage 变更

将添加一个新的表用于区域导入记录,以及样板 get、set、delete、update 方法。

新表 - zone_imports

类型

可为空?

唯一?

注意事项

id

uuid

主键

zone_id

uuid

导入完成后区域 ID

status

ENUM

以下之一:[COMPLETE, PENDING, ERROR]

message

VARCHAR

一条消息,告知用户他们的导入失败的原因。例如:“区域文件格式错误”、“完成”

其他变更

将为导入创建新的 DesignateObjects,ZoneImport、ZoneImportList。

区域导出也将回归 v2 API,但应保持相对不变。

替代方案

与其创建一个新的 zone_import 表和对象,不如可以创建一个空的域对象并调用 central._create_domain_in_storage,创建一个然后由导入结果更新的空域。只有这样才能调用池管理器。

这可能会使代码更简单。但几乎没有提供任何让用户知道他们的导入失败的方式。您可以添加一个像 MALFORMED_ZONEFILE 或类似的状态,但仍然需要用户在重试之前删除区域。除非您在失败时软删除区域,并修改默认的 find_domains 标准,仅在它们具有该状态时才查找已删除的区域。

负责人

主要负责人

tim-simmons-t

里程碑

完成目标里程碑

Liberty-1

工作项

  • 实现数据库表、迁移。

  • 实现存储方法。

  • 实现中央方法。

  • 修复 API 以使用新代码。

  • 将 API 移回 v2 命名空间