Ironic Neutron 集成

https://bugs.launchpad.net/ironic/+bug/1526403 https://bugs.launchpad.net/ironic/+bug/1618754

当前的 Ironic 实现仅支持扁平网络。为了隔离租户网络,Ironic 应该能够将信息传递给 Neutron,以便在租户网络上配置裸机服务器。

问题描述

Ironic 当前仅在扁平网络上配置服务器,因此无法在租户之间提供网络隔离。Ironic 应该允许最终用户像使用虚拟机一样,在隔离的网络(例如 VLAN、VXLAN)中使用裸机实例。

为了提供所需的网络隔离,Ironic 应该能够向 Neutron ML2 插件提供必要的连接信息(使用 LLDP),以便驱动程序可以为裸机服务器配置机架顶端(ToR)交换机。

Ironic 也会给 Neutron 带来新的挑战,例如链路聚合和每个节点上的多个网络的概念。本规范涵盖链路聚合的概念,即裸机服务器上的多个接口连接到单个 LAG 的交换机端口,并属于同一网络。但是,本规范不涵盖

  • 属于多个网络的干道端口——这需要 Neutron 的单独规范和实现,请参阅 vlan-aware-vms

  • 裸机服务器具有属于不同网络的多个接口的情况。这可能需要能够指定哪些 NIC 属于哪些网络的能力。这在范围内,但决定哪个接口获得哪个网络的方法将在其他地方确定。

提议的变更

当节点在 Ironic 中注册/检测时,应该为每个端口记录本地链路信息(例如 LLDP)。应该提供创建端口组来指定所述端口的聚合的选项。

Ironic 应该将本地链路信息以端口绑定配置文件的形式发送给 Neutron。对于每个端口组,端口绑定配置文件将包含该端口组中每个端口的本地链路信息列表。对于不属于端口组的每个端口,端口绑定配置文件将仅包含该特定端口的本地链路信息。因此,本地链路信息列表的长度可以被 Neutron 用于确定是为单个端口还是为端口组配置网络(在端口组的情况下,可能需要额外的交换机配置来管理关联的 LAG)。发送到 Neutron 端口创建 API 的每个端口绑定配置文件都将导致创建一个 Neutron 端口。这样,每个端口组都可以表示一个 LAG,其所有成员交换机端口都属于同一网络和同一网络段。

节点应该首先放置在配置网络上,然后放置在网络提供程序规范 [1] 中指定的租户网络上。为了帮助实现这一点,绑定配置文件中将存储一个变量,以记录是否请求了端口绑定。这将允许 Ironic 推迟绑定,直到 Ironic 能够填充 Neutron 所需的额外信息为止。

请注意,部署后将不支持 PXE 启动(即仅支持本地磁盘安装)。原因是,如果节点无法访问 TFTP 服务器,则无法通过 PXE 启动。对于部署在配置网络之外的任何节点,都需要使用本地启动。当使用此功能时,不应允许实例网络启动。如果将从每个租户网络到 TFTP 服务器设置路由,或者 Ironic 将与每个租户网络的 TFTP 服务器一起工作,则可以解决此限制,但这些选项在本规范中超出范围。

注意

虚拟媒体驱动程序在配置/租户网络隔离时可能同时支持网络启动和本地启动。这是因为虚拟媒体驱动程序使用带外方式通过 BMC 启动裸机,因此裸机服务器的 NIC 在启动实例时不需要访问 Ironic 调度器。

支持的 ML2 驱动程序可以使用提供的信息来配置端口。

Ironic 端口对象将使用新的 local_link_connection 字段进行更新,该字段提供以下值

  • switch_id

  • port_id

  • switch_info

这些字段采用字符串格式。可以使用 LLDP 基于 LLDP TLV 对应于 chassis_id、port_id 和 system_name 来收集信息,但并非严格要求使用 LLDP 值填充这些字段。例如,switch_id 字段用于标识交换机,可以是基于 LLDP 的 MAC 地址或基于 OpenFlow 的 datapath_id。switch_info 字段可用于区分不同的交换机型号或某些其他特定于供应商的标识符。switch_id 和 port_id 字段是必需的,switch_info 字段可以可选地填充。关键点是 Ironic 和 Neutron 应该对这些信息有相同的理解,以便将 Ironic 实例连接到适当的 Neutron 网络。

为了方便链路聚合,将创建一个新的端口组对象。除了基本对象之外,它还将具有以下字段

  • id

  • uuid

  • name

  • node_id

  • address

  • mode

  • properties

  • extra

  • internal_info

  • standalone_ports_supported

address 字段表示绑定 NIC 的 MAC 地址。它是可选的,因为它的值高度依赖于实例操作系统。在通过 nova 使用 ironic 的情况下,address 将被 neutron 为代表此端口组的 VIF 的地址生成的值填充,如果有的话。这发生在每次 VIF 附加调用期间。在独立模式下,它始终可以为 None,因为它应该通过 configdrive 在实例上配置。

mode 字段用于指定绑定模式。如果在端口组创建请求中未提供,则其默认值由 [DEFAULT]default_portgroup_mode 配置选项确定,而该配置选项的默认值为 active-backup。对于在较早的 API 版本中创建的端口组,此配置值将用作该端口组模式的值。active-backup 被选为默认值,因为此模式不需要交换机端进行任何额外的配置。

properties 字段是一个字典,可以包含配置端口组所需的任何参数。

有关 modeproperties 字段内容的更多信息,请参阅 linux kernel bonding documentation

extra 字段可用于保存操作员或开发人员想要存储在端口组中的任何其他信息。

internal_info 字段用于存储内部元数据。此字段是只读的。

standalone_ports_supported 指示端口组的成员端口是否可以用作独立端口。

Ironic 端口对象将添加以下字段以支持新功能

  • local_link_connection

  • portgroup_id

  • pxe_enabled

如果有多个 pxe_enabled 端口或端口组,则将为所有端口组和所有不属于任何端口组的 pxe_enabled 端口设置 dhcpboot 选项。

需要将以下端口绑定相关信息传递给 Neutron

字段名称

描述

vnic_type

配置文件的类型(在本例中为“baremetal”)。这将至少允许 ML2 驱动程序按 Ironic 端口进行基本过滤。

local_link_information

来自特定端口组中的所有 Ironic 端口或来自不属于任何端口组的单个 Ironic 端口的本地链路连接信息的列表。

host_id

应将其设置为 Ironic 节点 uuid。

描述结构的 JSON 示例是

{
  "port": {
    <all other fields>,
    "vnic_type": "baremetal",
    "host_id": <Ironic node UUID>,
    "binding:profile": {
      "local_link_information": [
        {
          "switch_id": xxx,
          "port_id": xxx,
          "switch_info": zzz,
          <optional more information>
        },
        {
          "switch_id": xxx,
          "port_id": yyy,
          "switch_info": zzz,
          <optional more information>
        }
      ]
      <some more profile fields>
    }
  }
}

备选方案

当前规定扁平网络的模型可以保持不变,使用相同的扁平网络用于所有内容。这并不是对本规范中提案的替代方案,而是坚持使用现有解决方案。

数据模型影响

提议的更改是在端口对象中添加以下字段及其数据类型和迁移默认值

字段名称

字段类型

迁移值

local_link_connection

dict_or_none

portgroup_id

int_or_none

pxe_enabled

bool

True

所有现有端口都将 pxe_enabled 设置为 true,以便不会更改当前行为。端口组关系是端口与端口组之间的 1:n 关系。

端口组对象将使用以下字段和数据类型提出

字段名称

字段类型

id

int

uuid

str

name

str_or_none

node_id

int_or_none

address

str_or_none

mode

str_or_none

properties

dict_or_none

extra

dict_or_none

internal_info

dict_or_none

standalone_ports_supported

bool

created_at

datetime_or_str_or_none

updated_at

datetime_or_str_or_none

注意

虽然端口组对象的 mode 属性的类型为 str_or_none,但其值不能为 None,除非数据库已手动更改。它在数据库迁移期间或在端口组创建期间(如果未显式指定)填充。在这两种情况下,它设置为 [DEFAULT]default_portgroup_mode 配置选项的值。

状态机影响

状态机不会直接受到影响,但是,只有当节点处于特定状态时,才允许对新的端口组对象进行更改和添加端口组。

当节点处于 MANAGEABLE/INSPECTING/ENROLL 状态时,可以更改端口组的端口成员资格。只有当节点处于 MANAGEABLE/INSPECTING/ENROLL 状态时,才能更新更新 local_link_connection 或 pxe_enabled 的任何端口更新。限制这些状态的原因是,更新这些新的端口属性将导致 binding_profile 中的 local_link_information 更新,这将触发 Neutron 中的更新。在预计不间断连接的情况下,仅允许在节点不在该状态时进行此操作可能是最安全的。这些限制还将确保 Neutron 端口更新仅在状态更改期间发生,而不是在任何端口更新调用时自动发生。

REST API 影响

将受到影响的以下端口 API 方法

  • /v1/ports

    • 检索端口列表。

    • 方法类型 GET。

    • http 响应代码未更改。如果指定了端口组资源但未找到,则 404 错误 http 响应代码将是另一个原因。

    • 可以包含新参数

      • portgroup (uuid_or_name) - 端口组的 UUID 或逻辑名称,仅获取该端口组的端口。

    • Body

    • 响应

      • 端口的 JSON 模式定义

  • /v1/ports/(port_uuid)

    • 检索给定端口的信息。

    • 方法类型 GET。

    • http 响应代码未更改。

    • 参数

      • port_uuid (uuid) - 端口的 UUID。

    • Body

    • 响应

      • 端口的 JSON 模式定义

  • /v1/ports

    • 创建一个新端口。

    • 方法类型为 POST。

    • http 响应代码未更改。

    • 参数

    • Body

      • 端口的 JSON 模式定义

    • 响应

      • 端口的 JSON 模式定义

  • /v1/ports/(port_uuid)

    • 更新现有端口。

    • 方法类型为 PATCH。

    • http 响应代码未更改。

    • 参数

      • port_uuid (uuid) - 端口的 UUID。

    • Body

      • 端口 Patch 的 JSON 模式定义

    • 响应

      • 端口的 JSON 模式定义

  • 端口的 JSON 模式定义(数据示例)

{
  "address": "fe:54:00:77:07:d9",
  "created_at": "2015-05-12T10:00:00.529243+00:00",
  "extra": {
    "foo": "bar",
  },
  "links": [
    {
      "href": "https://:6385/v1/ports/
       1004e542-2f9f-4d9b-b8b9-5b719fa6613f",
      "rel": "self"
    },
    {
      "href": "https://:6385/ports/
       1004e542-2f9f-4d9b-b8b9-5b719fa6613f",
      "rel": "bookmark"
    }
  ],
  "node_uuid": "e7a6f1e2-7176-4fe8-b8e9-ed71c77d74dd",
  "updated_at": "2015-05-15T09:04:12.011844+00:00",
  "uuid": "1004e542-2f9f-4d9b-b8b9-5b719fa6613f",
  "local_link_connection": {
    "swwitch_id": "0a:1b:2c:3d:4e:5f",
    "port_id": "Ethernet3/1",
    "switch_info": "switch1",
  },
  "portgroup_uuid": "6eb02b44-18a3-4659-8c0b-8d2802581ae4",
  "pxe_enabled": true
}
  • 端口 Patch 的 JSON 模式将是端口的 JSON 模式的子集。

将添加以下 API 方法以支持新的端口组模型

  • /v1/portgroups

    • 检索端口组列表。

    • 方法类型 GET。

    • 正常的 http 响应代码为 200。

    • 预期的错误 http 响应代码

      • 400 表示错误的查询或格式错误的语法(例如,如果地址不是 mac 地址格式)

      • 404 表示资源(例如,节点)未找到

    • 参数

      • node (uuid_or_name) - 节点的 UUID 或名称,仅获取该节点的端口组。

      • address (macaddress) - 端口组的 MAC 地址,仅获取具有此 MAC 地址的端口组。

      • marker (uuid) - 大型数据集的分页标记。

      • limit (int) - 在单个结果中返回的最大资源数。

      • sort_key (unicode) - 按其排序结果的列。默认值:id。

      • sort_dir (unicode) - 排序方向。“asc”或“desc”。默认值:asc。

    • Body

    • 响应

      • 端口组集合的 JSON 模式定义

  • /v1/portgroups/(portgroup_ident)

    • 检索给定端口组的信息。

    • 方法类型 GET。

    • 正常的 http 响应代码为 200。

    • 预期的错误 http 响应代码

      • 400 表示错误的查询或格式错误的语法

      • 404 表示资源(例如,端口组)未找到

    • 参数

      • portgroup_ident (uuid_or_name) - 端口组的 UUID 或逻辑名称。

    • Body

    • 响应

      • 端口组的 JSON 模式定义

  • /v1/portgroups

    • 创建一个新的端口组。

    • 方法类型为 POST。

    • 正常的 http 响应代码为 201。

    • 预期的错误 http 响应代码

      • 400 表示错误的查询或格式错误的语法

      • 409 表示资源冲突(例如,如果端口组名称已存在,因为名称应该是唯一的)

    • 参数

    • Body

      • 端口组的 JSON 模式定义

    • 响应

      • 端口组的 JSON 模式定义

  • /v1/portgroups/(portgroup_ident)

    • 删除端口组。

    • 方法类型为 DELETE。

    • 正常的 http 响应代码为 204。

    • 预期的错误 http 响应代码

      • 400 表示错误的查询或格式错误的语法

      • 404 表示资源(例如,端口组)未找到

    • 参数

      • portgroup_ident (uuid_or_name) - 端口组的 UUID 或逻辑名称。

    • Body

    • 响应

      • N/A

  • /v1/portgroups/(portgroup_ident)

    • 更新现有的端口组。

    • 方法类型为 PATCH。

    • 正常的 http 响应代码为 200。

    • 预期的错误 http 响应代码

      • 400 表示错误的查询或格式错误的语法

      • 404 表示资源(例如,端口组)未找到

      • 409 表示资源冲突(例如,如果端口组名称已存在,因为名称应该是唯一的)

    • 参数

      • portgroup_ident (uuid_or_name) - 端口组的 UUID 或逻辑名称。

    • Body

      • 端口组 Patch 的 JSON 模式定义

    • 响应

      • 端口组的 JSON 模式定义

  • /v1/portgroups/detail

    • 检索带有详细信息的端口组列表。额外的“detail”选项将返回所有字段,而没有它,只会返回字段的子集,即 uuid 和 address。

    • 方法类型 GET。

    • 正常的 http 响应代码为 200。

    • 预期的错误 http 响应代码

      • 400 表示错误的查询或格式错误的语法

      • 404 表示资源(例如,节点)未找到

    • 参数

      • node (uuid_or_name) - 节点的 UUID 或名称,仅获取该节点的端口组。

      • address (macaddress) - 端口组的 MAC 地址,仅获取具有此 MAC 地址的端口组。

      • marker (uuid) - 大型数据集的分页标记。

      • limit (int) - 在单个结果中返回的最大资源数。

      • sort_key (unicode) - 按其排序结果的列。默认值:id。

      • sort_dir (unicode) - 排序方向。“asc”或“desc”。默认值:asc。

    • Body

    • 响应

      • 带有详细信息的端口组集合的 JSON 模式定义。

  • /v1/nodes/(node_ident)/portgroups

    • 检索节点的端口组列表。

    • 方法类型 GET。

    • 正常的 http 响应代码为 200。

    • 预期的错误 http 响应代码

      • 400 表示错误的查询或格式错误的语法

      • 404 表示资源(例如,节点)未找到

    • 参数

      • node_ident (uuid_or_name) - 节点的 UUID 或逻辑名称。

    • Body

    • 响应

      • 端口组集合的 JSON 模式定义。

  • /v1/nodes/(node_ident)/portgroups/detail

    • 检索带有详细信息的节点的端口组列表。

    • 方法类型 GET。

    • 正常的 http 响应代码为 200。

    • 预期的错误 http 响应代码

      • 400 表示错误的查询或格式错误的语法

      • 404 表示资源(例如,节点)未找到

    • 参数

      • node_ident (uuid_or_name) - 节点的 UUID 或逻辑名称。

    • Body

    • 响应

      • 带有详细信息的端口组集合的 JSON 模式定义。

  • /v1/portgroups/(portgroup_ident)/ports

    • 检索端口组的端口列表。

    • 方法类型 GET。

    • 正常的 http 响应代码为 200。

    • 预期的错误 http 响应代码

      • 400 表示错误的查询或格式错误的语法

      • 404 表示资源(例如,端口组)未找到

    • 参数

      • portgroup_ident (uuid_or_name) - 端口组的 UUID 或逻辑名称。

    • Body

    • 响应

      • 端口集合的 JSON 模式定义。

  • /v1/portgroups/(portgroup_ident)/ports/detail

    • 检索端口组的带有详细信息的端口列表。

    • 方法类型 GET。

    • 正常的 http 响应代码为 200。

    • 预期的错误 http 响应代码

      • 400 表示错误的查询或格式错误的语法

      • 404 表示资源(例如,端口组)未找到

    • 参数

      • portgroup_ident (uuid_or_name) - 端口组的 UUID 或逻辑名称。

    • Body

    • 响应

      • 带有详细信息的端口集合的 JSON 模式定义。

  • 端口组(数据示例)的 JSON 模式定义

{
  "address": "fe:54:00:77:07:d9",
  "created_at": "2015-05-12T10:10:00.529243+00:00",
  "extra": {
    "foo": "bar",
  },
  "internal_info": {},
  "links": [
    {
      "href": "https://:6385/v1/portgroups/
      6eb02b44-18a3-4659-8c0b-8d2802581ae4",
      "rel": "self"
    },
    {
      "href": "https://:6385/portgroups/
      6eb02b44-18a3-4659-8c0b-8d2802581ae4",
      "rel": "bookmark"
    }
  ],
  "mode": "802.3ad",
  "name": "node1_portgroup1",
  "node_uuid": "e7a6f1e2-7176-4fe8-b8e9-ed71c77d74dd",
  "ports": [
    {
      "href": "http://127.0.0.1:6385/v1/portgroups/
      6eb02b44-18a3-4659-8c0b-8d2802581ae4/ports",
      "rel": "self"
    },
    {
      "href": "http://127.0.0.1:6385/portgroups/
      6eb02b44-18a3-4659-8c0b-8d2802581ae4/ports",
      "rel": "bookmark"
    }
  ],
  "properties": {
    "bond_xmit_hash_policy": "layer3+4",
    "bond_miimon": 100
  },
  "standalone_ports_supported": true,
  "updated_at": "2015-05-15T09:04:12.011844+00:00",
  "uuid": "6eb02b44-18a3-4659-8c0b-8d2802581ae4"
}
  • 端口组集合的 JSON 模式定义

{
  "portgroups": [
      {
          "address": "fe:54:00:77:07:d9",
          "links": [
              {
                  "href": "https://:6385/v1/portgroups/
                  6eb02b44-18a3-4659-8c0b-8d2802581ae4",
                  "rel": "self"
              },
              {
                  "href": "https://:6385/portgroups/
                  6eb02b44-18a3-4659-8c0b-8d2802581ae4",
                  "rel": "bookmark"
              }
          ],
          "name": "node1_portgroup1",
          "uuid": "6eb02b44-18a3-4659-8c0b-8d2802581ae4"
      }
  ]
}
  • 带有详细信息的端口组集合的 JSON 模式定义

{
  "portgroups": [
    {
      "address": "fe:54:00:77:07:d9",
      "created_at": "2016-08-18T22:28:48.165105+00:00",
      "extra": {},
      "internal_info": {},
      "links": [
        {
          "href": "http://127.0.0.1:6385/v1/portgroups/
          6eb02b44-18a3-4659-8c0b-8d2802581ae4",
          "rel": "self"
        },
        {
          "href": "http://127.0.0.1:6385/portgroups/
          6eb02b44-18a3-4659-8c0b-8d2802581ae4",
          "rel": "bookmark"
        }
      ],
      "mode": "802.3ad",
      "name": "node1_portgroup1",
      "node_uuid": "e7a6f1e2-7176-4fe8-b8e9-ed71c77d74dd",
      "ports": [
        {
          "href": "http://127.0.0.1:6385/v1/portgroups/
          6eb02b44-18a3-4659-8c0b-8d2802581ae4/ports",
          "rel": "self"
        },
        {
          "href": "http://127.0.0.1:6385/portgroups/
          6eb02b44-18a3-4659-8c0b-8d2802581ae4/ports",
          "rel": "bookmark"
        }
      ],
      "properties": {
        "bond_xmit_hash_policy": "layer3+4",
        "bond_miimon": 100
      },
      "standalone_ports_supported": true,
      "updated_at": "2016-11-04T17:46:09+00:00",
      "uuid": "6eb02b44-18a3-4659-8c0b-8d2802581ae4"
    }
  ]
}
  • 端口组 Patch 的 JSON 模式将是端口组的 JSON 模式的子集。

API 微版本是否需要递增?

  • 是的。

包括典型 API 示例的示例用例,用于调用方提供的数据和响应。

  • 端口创建示例。

    • 提供的数据

    {
      "address": "fe:54:00:77:07:d9",
      "node_uuid": "e7a6f1e2-7176-4fe8-b8e9-ed71c77d74dd",
      "local_link_connection": {
        "switch_id": "0a:1b:2c:3d:4e:5f",
        "port_id": "Ethernet3/1",
        "switch_info": "switch1",
        },
      "pxe_enabled": true
    }
    
    • 响应 201,带有正文

    {
      "address": "fe:54:00:77:07:d9",
      "node_uuid": "e7a6f1e2-7176-4fe8-b8e9-ed71c77d74dd",
      "local_link_connection": {
        "switch_id": "0a:1b:2c:3d:4e:5f",
        "port_id": "Ethernet3/1",
        "switch_info": "switch1",
        },
      "pxe_enabled": true
      "created_at": "2015-05-12T10:00:00.529243+00:00",
      "extra": {
      },
      "links": [
        {
          "href": "https://:6385/v1/ports/
           1004e542-2f9f-4d9b-b8b9-5b719fa6613f",
          "rel": "self"
        },
        {
          "href": "https://:6385/ports/
           1004e542-2f9f-4d9b-b8b9-5b719fa6613f",
          "rel": "bookmark"
        }
      ],
      "updated_at": null,
      "uuid": "1004e542-2f9f-4d9b-b8b9-5b719fa6613f",
      "portgroup_uuid": null,
    }
    
  • 端口组创建示例。

    • 提供的数据

    {
      "address": "fe:54:00:77:07:d9",
      "node_uuid": "e7a6f1e2-7176-4fe8-b8e9-ed71c77d74dd",
      "standalone_ports_supported": true,
      "name": "node1_portgroup1"
    }
    
    • 响应 201,带有正文

    {
      "address": "fe:54:00:77:07:d9",
      "node_uuid": "e7a6f1e2-7176-4fe8-b8e9-ed71c77d74dd",
      "name": "node1_portgroup1"
      "created_at": "2015-05-12T10:10:00.529243+00:00",
      "extra": {
      },
      "internal_info": {},
      "links": [
        {
          "href": "https://:6385/v1/portgroups/
           6eb02b44-18a3-4659-8c0b-8d2802581ae4",
          "rel": "self"
        },
        {
          "href": "https://:6385/portgroups/
           6eb02b44-18a3-4659-8c0b-8d2802581ae4",
          "rel": "bookmark"
        }
      ],
      "mode": null,
      "ports": [
        {
          "href": "http://127.0.0.1:6385/v1/portgroups/
          6eb02b44-18a3-4659-8c0b-8d2802581ae4/ports",
          "rel": "self"
        },
        {
          "href": "http://127.0.0.1:6385/portgroups/
          6eb02b44-18a3-4659-8c0b-8d2802581ae4/ports",
          "rel": "bookmark"
        }
      ],
      "properties": {},
      "standalone_ports_supported": true,
      "updated_at": null,
      "uuid": "6eb02b44-18a3-4659-8c0b-8d2802581ae4",
    }
    
  • 端口更新示例。

    • 参数“port_uuid”=”1004e542-2f9f-4d9b-b8b9-5b719fa6613f”

    • 提供的数据(JSON PATCH 语法,其中“op”可以是 add/replace/delete)

    [{"path": "/portgroup_uuid", "value":
      "6eb02b44-18a3-4659-8c0b-8d2802581ae4", "op": "add"}]
    
    • 响应 200,带有正文

    {
      "address": "fe:54:00:77:07:d9",
      "node_uuid": "e7a6f1e2-7176-4fe8-b8e9-ed71c77d74dd",
      "local_link_connection": {
        "switch_id": "0a:1b:2c:3d:4e:5f",
        "port_id": "Ethernet3/1",
        "switch_info": "switch1",
        },
      "pxe_enabled": true
      "created_at": "2015-05-12T10:00:00.529243+00:00",
      "extra": {
      },
      "links": [
        {
          "href": "https://:6385/v1/ports/
           1004e542-2f9f-4d9b-b8b9-5b719fa6613f",
          "rel": "self"
        },
        {
          "href": "https://:6385/ports/
           1004e542-2f9f-4d9b-b8b9-5b719fa6613f",
          "rel": "bookmark"
        }
      ],
      "updated_at": "2015-05-12T10:20:00.529243+00:00",
      "uuid": "1004e542-2f9f-4d9b-b8b9-5b719fa6613f",
      "portgroup_uuid": "6eb02b44-18a3-4659-8c0b-8d2802581ae4",
    }
    
    • 请注意,端口更新 API 应该支持更新端口对象的 portgroup_id。这将允许操作员迁移现有部署。

  • 端口列表示例。

    • 参数“node_uuid”=”e7a6f1e2-7176-4fe8-b8e9-ed71c77d74dd”

    • 响应 200,带有正文

    {"ports": [
      {
      "address": "fe:54:00:77:07:d9",
      "links": [
        {
          "href": "https://:6385/v1/ports/
           1004e542-2f9f-4d9b-b8b9-5b719fa6613f",
          "rel": "self"
        },
        {
          "href": "https://:6385/ports/
           1004e542-2f9f-4d9b-b8b9-5b719fa6613f",
          "rel": "bookmark"
        }
      ],
      "uuid": "1004e542-2f9f-4d9b-b8b9-5b719fa6613f",
      "portgroup_uuid": "6eb02b44-18a3-4659-8c0b-8d2802581ae4",
      }
    ]}
    
    • 请注意,portgroup_uuid 现在在响应中返回。

讨论任何策略更改,并讨论部署者在定义其策略时需要考虑的事情。

  • Ironic 具有仅管理员策略,因此策略定义不必担心。

  • 部署者应了解特定 ML2 驱动程序支持使用通过 binding_profile 传递给它的新的 local_link_information 的能力。

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

  • 客户端库和 CLI 应更新以支持新的 API。

此更改是否可被客户端发现?并非所有客户端都会同时升级,因此此更改必须与旧客户端协同工作,而不会破坏它们。

  • 对 API 的更改将向后兼容,因此旧客户端仍将继续按原样工作。

客户端 (CLI) 影响

python-ironicclient 和 OSC 需要更新以支持新的 portgroups API。

在下面的命令中,<portgroup> 表示此占位符可以包含 portgroup UUID 或名称。 <portgroup_uuid> 只能包含 portgroup UUID。

新方法的使用示例

  • 对于端口,CLI 将支持使用新的可选参数创建端口,这些参数指定新的端口属性(local_link_connection、portgroup_id 和 pxe_enabled),并支持更新这些属性。例如

    “ironic” CLI

    • ironic port-create -a <address> -n <node> [-e <key=value>] [–local-link-connection <key=value>] [–portgroup <portgroup>] [–pxe-enabled <boolean>]

    • ironic port-update <port_uuid> add portgroup_uuid=<portgroup_uuid> –local-link-connection <key=value> –pxe-enabled <boolean>

    “openstack baremetal” CLI

    • openstack baremetal port create –node <node> [–local-link-connection <key=value>] [–port-group <portgroup>] [–pxe-enabled <boolean>] <address>

    • openstack baremetal port set [–port-group <portgroup>] [–local-link-connection <key=value>] [–pxe-enabled <boolean>] <port>

    • openstack baremetal port list [–address <mac-address>] [–node <node> | –port-group <portgroup>]

  • 对于 portgroups,CLI 将支持以下新方法

    “ironic” CLI

    • ironic portgroup-create –node <node> [–address <mac-address>] [–name <portgroupname>] [-e <key=value>] [–standalone-ports-supported <boolean>] [-m <mode>] [-p <key=value>]

    • ironic portgroup-delete <portgroup> [<portgroup> …]

    • ironic portgroup-list [–detail | –fields <field> [<field> …]] [–node <node>] [–address <mac-address>] [–limit <limit>] [–marker <portgroup_uuid>] [–sort-key <field>] [–sort-dir <direction>]

    • ironic portgroup-port-list [–detail | –fields <field> [<field> …]] [–limit <limit>] [–marker <portgroup_uuid>] [–sort-key <field>] [–sort-dir <direction>] <portgroup>

    • ironic portgroup-show [–address] [–fields <field> [<field> …]] <id>

      • <id> 是 portgroup 的 UUID 或名称(如果指定了 –address,则是 MAC 地址)

    • ironic portgroup-update <portgroup> <op> <path=value> [<path=value> … ]

      • <op> 是 add、remove 或 replace。

      • <path=value> 是要添加、删除或替换的属性。可以多次指定。对于“remove”,仅需要 <path>。

    • 注意:即使 ironic CLI 包含 ‘ironic node-port-list’,我们不会提供相应的 ‘ironic node-portgroup-list’。相反,节点的 portgroup 列表将通过 ironic portgroup-list –node 提供。

    “openstack baremetal” CLI

    • openstack baremetal port group create –node <uuid> [–name <name>] [–extra <key=value>] [–support-standalone-ports | –unsupport-standalone-ports] [–mode <mode>] [–properties <key=value>] [–address <mac-address>]

    • openstack baremetal port group delete <portgroup> [<portgroup> …]

    • openstack baremetal port group list [–marker <portgroup>] [–address <mac-address>] [–node <node>] [–sort <key>[:<direction>]] [–long | –fields <field> [<field> …]]

    • openstack baremetal port group show [–address] [–fields <field> [<field> …]] <id>

      • <id> 是 portgroup 的 UUID 或名称(如果指定了 –address,则是 MAC 地址)

    • openstack baremetal port group set [–address <mac-address>] [–name <name>] [–node <node>] [–extra <key=value>] [–support-standalone-ports | –unsupport-standalone-ports] [–mode <mode>] [–properties <key=value>] <portgroup>

    • openstack baremetal port group unset [–address] [–name] [–extra <key>] [–properties key] <portgroup>

    • 要将端口添加到 portgroup,应先创建 portgroup,然后调用 port_update 或 port create。

python-ironicclient 也需要扩展 Port 详细资源,以包含新的端口属性。

RPC API 影响

对现有 API 调用的影响为零。

需要新的 RPC API 调用

  • update_portgroup

  • destroy_portgroup

这些新的 API 调用将使用 call()。与 update_port 的现有 API 调用一样,update_portgroup 的新 API 调用应在更新地址字段时请求 DHCP 更新。

将此更改推广到现有部署,应先升级 ironic-conductor,然后再升级 ironic-api。

驱动程序 API 影响

ironic/dhcp/neutron 中的 NeutronDHCPApi 类使用 DHCP 选项更新 Neutron 端口。vifs 在 ironic/common/network 中通过从 Ironic 端口的 extra 属性中提取 vif_port_id 来获得。如果 vifs 也绑定到 portgroups,则应更新此方法。

互补的网络提供商规范 [1] 提供了有关网络切换的流程以及将 binding profile 传递给 Neutron 以绑定端口的点的详细信息。

Nova 驱动程序影响

由于此工作取决于 attach/detach 接口工作 [2],因此完全支持 portgroups 所需做的唯一事情是 configdrive 生成。

Nova 将调用 ironic 以获取与 VIF 关联的每个 portgroup 的端口列表,以及 portgroup mode 和 properties 字段(参见 数据模型影响 部分),并使用所需的信息更新网络元数据。当将 properties 字典的内容传递给 nova 中的 config drive 构建器时,我们将确保将 bond_ 前缀添加到所有键名之前,以便 cloud-init 在读取 config drive 时不会忽略这些键。

Ramdisk 影响

N/A

安全影响

新的 portgroups REST API 调用不应可供最终用户使用。只有操作员和管理员才能管理 portgroups 和端口的 local_link_connection 数据,因为这些设置用于配置网络。由于 Ironic 是仅管理员 API,因此不应存在安全影响。

其他最终用户影响

使用 binding profile 启用置备网络和租户网络之间的切换意味着部署后将不支持 PXE 启动(即仅支持本地磁盘安装)。应在互补的网络提供商规范 [1] 中讨论如何允许操作员使用相同的 Ironic conductor 使用 net-boot 或 local boot 部署实例。

可扩展性影响

将进行更多 API 调用到 Ironic 以创建和使用 portgroups,但对可伸缩性的影响应可以忽略不计。

性能影响

无。

其他部署者影响

将向端口表添加新的数据库列,并引入一个新的数据库表 portgroup,因此这将需要数据库迁移。

部署者需要部署支持将裸机资源连接到 Neutron 网络的 ML2 机制驱动程序。

如果使用 Nova,部署者需要部署支持此功能的 Nova 版本。

部署者可能希望设置 [DEFAULT]default_portgroup_mode 配置选项以匹配其环境。其默认值为 active-backup

部署者应注意,不支持已置备节点的自动化升级或迁移。部署者应遵循此建议以升级现有部署中的节点以使用此新功能

  • 升级 OpenStack 服务。

  • 将节点移动到 MANAGEABLE 状态。

  • 更新节点驱动程序字段(参见网络提供商规范 [1])。

  • 创建 Ironic portgroups。

  • 更新 Ironic 端口的 portgroup 成员关系。

  • 使用 local_link_connection 数据更新 Ironic 端口。

  • 将节点移动到 AVAILABLE 状态。

开发人员影响

Neutron ML2 机制驱动程序应通过使用 binding profile 中传递的数据动态配置相关交换机上的相关端口和端口通道来支持此功能。

实现

负责人

  • laura-moore

  • yhvh (Will Stevenson)

  • bertiefulton

  • sukhdev-8

  • vsaienko

  • vdrok

工作项

  • 扩展端口表。

  • 创建新的 portgroup 表。

  • 实现对端口 API 的扩展。

  • 实现新的 portgroup API。

  • 实现对 RPC API 的扩展。

  • 实现更改 Nova 驱动程序以获取和使用 binding profile。

  • 实现更新 Neutron 端口 DHCP 选项所需的更改以获取 vifs。

  • 实现新功能的测试。

  • 实现对 python-ironicclient 的更新。

  • 更新文档。

依赖项

网络切换取决于网络提供商规范 [1]

Nova 更改 取决于 attach/detach 接口工作 [2]

交换机上的 VLAN 置备取决于 ML2 驱动程序功能正在开发以支持此功能。

测试

默认行为将在 gate 中默认进行测试。

需要编写新的测试来测试新的 API 和数据库更新。

网络提供商规范 [1] 描述了为测试目的模拟连接到真实交换机的真实硬件。

升级和向后兼容性

默认行为是当前行为,因此此更改应完全向后兼容。

文档影响

此功能将完全记录。

参考资料

关于此主题的讨论包括