Boot Interface in Ironic¶
This spec talks about refactoring the boot logic out of the current Ironic “deploy” drivers into a new boot interface.
Current we have a DeployInterface in Ironic. All the current implementations of this interface are responsible for two things:
Booting the bare metal node - both deploy ramdisk and the deployed instance.
Actual deployment of an image on a bare metal node.
These are two separate functions and therefore should be abstracted separately. This makes it easy to mix and match various boot mechanisms (like PXE, iPXE, virtual media) with various deploy mechanisms (iscsi deploy, agent deploy and various other deploy mechanisms which may be possible like deploying with torrent, multicast, etc in which discussions have been initiated) without duplicating code.
BootInterfaceneeds to be added. The interface will recommend the following methods for the implementor:
@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. """
The following new implementations of
BootInterfacewill be created.
pxe.PXEBoot- Booting a bare metal node using PXE
ipxe.IPXEBoot- Booting a bare metal node using iPXE
ilo.boot.IloVirtualMediaBoot- Booting a bare metal node using iLO Virtual Media.
Even though IPXEBoot and PXEBoot are in same deploy driver currently, the steps for preparing a bare metal to boot from PXE and iPXE are different (even though they share some common code). We will refactor both of them as separate boot interfaces. The Kilo behaviour of using only either of PXE or iPXE at same time will be retained - drivers will instantiate pxe.PXEBoot or ipxe.IPXEBoot depending on CONF.pxe.ipxe_enabled.
The code for the above implementations of
BootInterfacewill be taken from
ilo.IloVirtualMediaAgentDeploy. These implementations of
DeployInterfacewill be freed of any logic dealing with booting of bare metal node.
pxe.PXEDeploywill be refactored into
Each driver will mention what is the
BootInterfaceimplementation that it wishes to instantiate. For example, the
pxe_ipmitooldriver will look like the following:
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')
It might make sense to rename the drivers to include the boot interface as well as deploy interface after this is implemented. As such, this requires a better thought out process to rename the drivers, address issues of backward compatibility, etc. Hence it is out of scope of this spec. That can be addressed later after this is implemented.
We can continue to keep the boot and deploy logic together but this will lead to code duplications and unnecessary refactorings when additional deploy mechanisms and boot mechanisms are added in the future.
Data model impact¶
State Machine Impact¶
REST API impact¶
RPC API impact¶
Client (CLI) impact¶
Driver API impact¶
This adds the a new
BootInterface (as described above) which driver
writers may use with the deploy drivers.
BootInterface is not a
Nova driver impact¶
Other end user impact¶
Other deployer impact¶
New driver developers adding new deploy mechanisms in Ironic will be encouraged to separate boot and deploy logic so that it can reused easily.
Add new boot interface
iscsi_deploy.ISCSIDeployto make use of these boot interfaces.
agent.AgentDeployto use new
ipxe.IPXEBoot(Yes, we are adding iPXE support for agent deploy).
ilo.boot.IloVirtualMediaBoot, and refactor
IloVirtualMediaAgentDriverto make use of the new boot interface.
Unit tests will be updated for the new interfaces. Since this change doesn’t add any new functionality, the current upstream CI testing should be enough.
Upgrades and Backwards Compatibility¶
This doesn’t break out-of-tree deploy drivers. Still it will be possible
to implement deploy drivers for provisioning bare metal nodes without a boot
interface- i.e without separate boot and deploy interfaces. This is because
the conductor will still be using all the published interfaces of
DeployInterface for deploying a bare metal node.
This change proposes the addition of new optional boot interface which can be
used as a helper for
DeployInterface and refactors all upstream deploy
drivers to follow this logic.
Changes to the existing interface will be documented. Also, new developer documentation will be updated to encourage splitting deploy logic into separate boot and deploy interfaces.