Ironic 中的启动接口¶
https://blueprints.launchpad.net/ironic/+spec/new-boot-interface
本文档描述了将启动逻辑从当前 Ironic 的“部署”驱动程序中重构到新的启动接口。
问题描述¶
目前 Ironic 中有一个 DeployInterface。该接口的所有当前实现都负责两件事
启动裸机节点 - 包括部署 ramdisk 和部署的实例。
在裸机节点上实际部署镜像。
这两者是独立的函数,因此应该分别抽象出来。这使得可以轻松地将各种启动机制(如 PXE、iPXE、虚拟介质)与各种部署机制(iscsi 部署、agent 部署以及其他可能的部署机制,例如通过 torrent、multicast 部署,相关讨论已经开始)混合和匹配,而无需重复代码。
提议的变更¶
需要添加一个新的
BootInterface。该接口将建议实现者采用以下方法@six.add_metaclass(abc.ABCMeta) class BootInterface(object): """Interface for inspection-related actions.""" @abc.abstractmethod def get_properties(self): """Return the properties of the interface. :returns: dictionary of <property name>:<property description> """ @abc.abstractmethod def validate(self, task): """Validate the driver-specific info for booting. This method validates the driver-specific info for booting a ramdisk and an instance on the node. If invalid, raises an exception; otherwise returns None. :param task: a task from TaskManager. :raises: InvalidParameterValue :raises: MissingParameterValue """ @abc.abstractmethod def prepare_ramdisk(self, task, ramdisk_params): """Prepares the boot of Ironic ramdisk. This method prepares the boot of the deploy ramdisk after reading relevant information from the node's database. :param task: a task from TaskManager. :param ramdisk_params: the options to be passed to the ironic ramdisk. Different interfaces might want to boot the ramdisk in different ways by passing parameters to them. For example, * When DIB ramdisk is booted to deploy a node, it takes the parameters iscsi_target_iqn, deployment_id, ironic_api_url, etc. * When Agent ramdisk is booted to deploy a node, it takes the parameters ipa-driver-name, ipa-api-url, root_device, etc. Other interfaces can make use of ramdisk_params to pass such information. Different implementations of boot interface will have different ways of passing parameters to the ramdisk. """ @abc.abstractmethod def clean_up_ramdisk(self, task): """Tears down the boot of Ironic ramdisk. This method tears down the boot of the deploy ramdisk after reading relevant information from the node's database. :param task: a task from TaskManager. """ @abc.abstractmethod def prepare_instance(self, task): """Prepares the boot of instance. This method prepares the boot of the instance after reading relevant information from the node's database. :param task: a task from TaskManager. """ @abc.abstractmethod def clean_up_instance(self, task): """Tears down the boot of instance. This method tears down the boot of the instance after reading relevant information from the node's database. :param task: a task from TaskManager. """
将创建以下新的
BootInterface实现。pxe.PXEBoot- 使用 PXE 启动裸机节点ipxe.IPXEBoot- 使用 iPXE 启动裸机节点ilo.boot.IloVirtualMediaBoot- 使用 iLO 虚拟介质启动裸机节点。
注意
虽然 IPXEBoot 和 PXEBoot 目前在同一个部署驱动程序中,但准备裸机以从 PXE 和 iPXE 启动的步骤是不同的(即使它们共享一些通用代码)。我们将把它们重构为单独的启动接口。Kilo 行为,即同时只使用 PXE 或 iPXE,将保留 - 驱动程序将根据 CONF.pxe.ipxe_enabled 实例化 pxe.PXEBoot 或 ipxe.IPXEBoot。
上述
BootInterface实现的代码将从pxe.PXEDeploy、agent.AgentDeploy、ilo.IloVirtualMediaIscsiDeploy和ilo.IloVirtualMediaAgentDeploy中获取。这些DeployInterface实现将不再包含任何与裸机节点启动相关的逻辑。pxe.PXEDeploy将被重构为pxe.PXEBoot和iscsi_deploy.ISCSIDeploy。每个驱动程序将说明它希望实例化哪个
BootInterface实现。例如,pxe_ipmitool驱动程序将如下所示class PXEAndIPMIToolDriver(base.BaseDriver): """PXE + IPMITool driver""" def __init__(self): self.power = ipmitool.IPMIPower() self.console = ipmitool.IPMIShellinaboxConsole() self.boot = pxe.PXEBoot() self.deploy = iscsi_deploy.ISCSIDeploy() self.management = ipmitool.IPMIManagement() self.vendor = pxe.VendorPassthru() self.inspect = discoverd.DiscoverdInspect.create_if_enabled( 'PXEAndIPMIToolDriver')
注意
在实现后,将启动接口也包含在驱动程序名称中可能是有意义的。因此,这需要一个更周全的过程来重命名驱动程序,解决向后兼容性问题等。因此,这不在本文档的范围内。可以在实现后稍后解决。
备选方案¶
我们可以继续将启动和部署逻辑放在一起,但这会导致代码重复和不必要的重构,尤其是在未来添加额外的部署机制和启动机制时。
数据模型影响¶
无。
状态机影响¶
无。
REST API 影响¶
无。
RPC API 影响¶
无。
客户端 (CLI) 影响¶
无。
驱动程序 API 影响¶
这添加了一个新的 BootInterface(如上所述),驱动程序编写者可以使用它与部署驱动程序一起使用。BootInterface 不是一个强制接口。
Nova 驱动程序影响¶
无。
安全影响¶
无。
其他最终用户影响¶
无。
可扩展性影响¶
无。
性能影响¶
无。
其他部署者影响¶
无。
开发人员影响¶
鼓励在 Ironic 中添加新部署机制的新驱动程序开发人员将启动和部署逻辑分离,以便可以轻松地重用它。
实现¶
负责人¶
rameshg87
工作项¶
添加新的启动接口
创建
pxe.PXEBoot、ipxe.IPXEBoot并重构pxe.PXEDeploy为iscsi_deploy.ISCSIDeploy以使用这些启动接口。重构
agent.AgentDeploy以使用新的pxe.PXEBoot和ipxe.IPXEBoot(是的,我们正在为 agent 部署添加 iPXE 支持)。创建
ilo.boot.IloVirtualMediaBoot,并重构IloVirtualMediaIscsiDriver、IloVirtualMediaAgentDriver以使用新的启动接口。
依赖项¶
无。
测试¶
将更新新接口的单元测试。由于此更改没有添加任何新功能,因此当前的 upstream CI 测试应该足够。
升级和向后兼容性¶
这不会破坏树外的部署驱动程序。仍然可以实现用于配置裸机节点的部署驱动程序,而无需启动接口 - 即无需单独的启动和部署接口。这是因为 conductor 仍然将使用所有已发布的 DeployInterface 接口来部署裸机节点。
此更改提出了一个新的可选启动接口的添加,该接口可以用作 DeployInterface 的辅助工具,并重构所有 upstream 部署驱动程序以遵循此逻辑。
文档影响¶
现有接口的更改将记录在案。此外,新的开发人员文档将更新,以鼓励将部署逻辑拆分为单独的启动和部署接口。
参考资料¶
不符合本文档的要求,但一个 POC 演示其外观:* https://review.openstack.org/#/c/166512/ * https://review.openstack.org/#/c/166513/ * https://review.openstack.org/#/c/166521/