Ironic 接口连接和断开 API

https://bugs.launchpad.net/ironic/+bug/1582188

我们正在向 Ironic 添加可插拔的网络接口。这些接口将可配置为每个 Ironic 节点,这意味着不同的节点可能具有不同的方式来处理它们网络接口。我们需要一种方式,让不同的网络接口能够覆盖 nova 中当前包含的虚拟网络接口 (VIF) 到物理网络接口 (PIF) 映射逻辑。

问题描述

目前,我们使用 Ironic 端口更新,通过其 extra 字段将租户 neutron 端口分配给 Ironic 端口。以这种方式进行映射可能不适用于第三方网络接口实现。这也会将 ironic nova virt 驱动程序绑定到特定的网络 VIF 到 PIF 映射实现。如果第三方网络接口想要对网络 VIF 到 PIF 映射做不同的事情,例如在配置过程后期存储端口 ID 以进行动态 vNIC 创建,或者作为 Ironic 团队,我们想要更改实现细节,则必须提交到 nova 的更改。此外,如果我们要支持网络 VIF 的部署后连接和断开,则必须监视对端口对象所做的任何更新,并将某些更改解释为某些操作。

提议的变更

为了解决这个问题,我建议添加一个新的 API 端点:

  • POST v1/nodes/<node_id>/vifs

  • GET v1/nodes/<node_id>/vifs

  • DELETE v1/nodes/<node_id>/vifs/<vif_id>

这些 API 端点将通过 POST 请求体接收一个通用 VIF 对象的 JSON 表示形式。使其通用允许基于非 neutron 的实现使用此 API。这个 VIF 对象将被传递给可插拔网络接口中的新函数

def vif_attach(self, vif)

def vif_detach(self, vif_id)

def vif_list(self)

网络接口可以使用这些函数来处理以其实现所需的方式将 VIF 连接到 Ironic 节点。这可以通过将字段添加到 Ironic 端口(如现有实现)或以不同的方式完成,例如将其存储在节点驱动程序_internal_info 中的列表中。

ironic nova virt 驱动程序将被更新为使用此新的 API,在 plug_vifs 和 unplug_vifs 函数中,将其与底层实现细节解耦。

备选方案

  • 继续使用端口更新,以允许 nova 与 ironic 端口以及即将推出的端口组进行交互,并将 vif_port_id 等逻辑记录为网络接口使用的定义 API。

数据模型影响

状态机影响

REST API 影响

  • GET v1/nodes/<node_id>/vifs

    • 调用节点网络接口上的 vif_list

    • 这是一个同步 API 端点,正常的 ironic 规则适用于避免在同步端点下实现需要很长时间或不稳定的任务。

    • 方法:GET

    • 成功的 http 响应:200

    • 预期的响应体是一个 JSON

      • JSON Schema

        {
            "title": "VIFS",
            "type": "object",
            "properties": {
                "vifs": {
                    "description": "List of VIFs currently attached"
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            }
                        },
                        "required": ["id"]
                    }
                }
            },
            "required": ["vifs"]
        }
        
      • 示例

        {
            "vifs": [
                        {
                            "id": "8e6ba175-1c16-4dfa-82b9-dfc12f129170",
                        }
            ]
        }
        
  • POST v1/nodes/<node_id>/vifs

    • 调用网络接口上的 vif_attach,传入提供的 json

    • 这是一个同步 API 端点,正常的 ironic 规则适用于避免在同步端点下实现需要很长时间或不稳定的任务。

    • 方法:POST

    • 成功的 http 响应:204

    • 预期的错误响应代码

      • 404,节点未找到

      • 400,请求格式错误

      • 409,请求的 VIF 与已连接的其他 VIF 之间存在冲突

      • 422,请求有效,但由于定义的原因无法连接 VIF,例如:“没有可用的物理接口连接”

    • 预期数据是一个 JSON

      • JSON Schema

        {
            "title": "Attachment",
            "type": "object",
            "properties": {
                "id": {
                    "description": "ID of VIF to attach"
                    "type": "string"
                },
            },
            "required": ["id"]
        }
        
      • 示例

        {
          "id": "8e6ba175-1c16-4dfa-82b9-dfc12f129170"
        }
        
    • 预期的响应体为空

  • DELETE v1/nodes/<node_id>/vifs/<vif_id>

    • 调用网络接口上的 vif_detach,传入提供的 json

    • 这是一个同步 API 端点,正常的 ironic 规则适用于避免在同步端点下实现需要很长时间或不稳定的任务。

    • 方法:DELETE

    • 成功的 http 响应:204

    • 预期的错误响应代码

      • 404,节点未找到

      • 400,请求格式错误

      • 422,请求有效,但由于定义的原因无法断开 VIF

    • 预期的响应体为空。

  • API 是否需要递增微版本? 是

  • 客户端库和 CLI 是否需要相应的更改? 是

  • 由于这些是新的 API 入口点,它们不会影响旧的客户端。

客户端 (CLI) 影响

“ironic” CLI

  • ironic node-vif-list <node_id>

  • ironic node-vif-attach <node_id> <vif_id>

  • ironic node-vif-detach <node_id> <vif_id>

“openstack baremetal” CLI

  • openstack baremetal node vif list <node_id>

  • openstack baremetal node vif attach <node_id> <vif_id>

  • openstack baremetal node vif detach <node_id> <vif_id>

RPC API 影响

RPC API 将实现

  • vif_attach(self, context, node_id, vif)

  • vif_detach(self, context, node_id, vif_id)

  • vif_list(self, context, node_id)

驱动程序 API 影响

基础网络接口需要扩展为

def vif_list(self, task):
    # TODO(sambetts): Uncomment when vif_port_id in port.extra is removed.
    # raise NotImplemented
    default_vif_list()

def vif_attach(self, task, vif):
    # TODO(sambetts): Uncomment when vif_port_id in port.extra is removed.
    # raise NotImplemented
    default_vif_attach(vif)

def vif_detach(self, task, vif_id):
    # TODO(sambetts): Uncomment when vif_port_id in port.extra is removed.
    # raise NotImplemented
    default_vif_detach(vif_id)

现有的 flat、neutron 和 noop 网络接口需要扩展,以包含这些函数的实现。

Flat 网络驱动程序需要实现 add_provisioning_network,以绑定以前由 nova 绑定的端口。

Nova 驱动程序影响

plug/unplug_vifs 逻辑将被替换为调用 attach/detach,以处理传递到这些函数中的每个 VIF。

nova.virt.driver.IronicDriver.macs_for_instance 将被删除,因为映射在 Ironic 内部处理,因此 mac_address 分配必须在过程后期的绑定时发生。

nova.virt.driver.IronicDriver.network_binding_host_id 将更改为在所有情况下返回 None,以便 neutron 端口在 Ironic 在部署期间绑定它们之前保持未绑定状态。

nova 驱动程序需要将 nova 计算主机 ID 包含在 instance_info 中,以便 ironic flat 网络接口可以使用它来更新 neutron 端口,从而模拟现有的 nova 行为。

nova 驱动程序 ironic API 版本要求需要增加到实现 attach 和 detach API 的版本。操作员需要确保 nova 计算服务上安装的 python-ironicclient 版本支持新的 API。

Ramdisk 影响

安全影响

其他最终用户影响

可扩展性影响

性能影响

其他部署者影响

开发人员影响

网络接口的开发人员需要考虑他们的网络接口希望如何处理端口。

实现

负责人

主要负责人

sambetts

工作项

  • 向 Ironic 添加新的 API

  • 更新现有的 ironic 网络接口以支持新的 API

  • 向 ironic 客户端添加新的 API

  • 更新 nova virt 驱动程序以通过客户端使用新的 API

依赖项

测试

这些更改将在正常的 gate 过程中进行测试,因为它们将是正常的 ironic 部署工作流程的一部分。

升级和向后兼容性

通过端口/端口组更新设置 vif_port_id 将被弃用,以支持新的 API。如果用户直接在端口或端口组上设置 vif_port_id,则应发出弃用消息。需要添加代码以确保网络接口仍然处理通过该方法设置的 vif_port_id。

由于旧的 vif_port_id 字段仍然受支持但已弃用,旧的 nova virt 驱动程序将继续使用该方法工作。

必须先升级 Ironic,然后再升级 Nova,因为较新的 nova virt 驱动程序将无法与缺少新 API 的旧 Ironic 版本一起工作。

树外网络接口可能不会立即实现 interface_attach 和 interface_detach 方法,因此在 vif_port_id 是弃用方法期间,我们还应确保提供 attach 和 detach 的默认实现,此默认实现应匹配 ironic nova virt 驱动程序实现将 vif_port_id 设置在 port.extra 中的行为,并在删除 port.extra 中 vif_port_id 的支持时将被删除。

文档影响

需要记录新的 API 及其用法。

参考资料