Ansible is a mature and popular automation tool, written in Python and requiring no agents running on the node being configured. All communications with the node are by default performed over secure SSH transport.
The ansible
deploy interface uses Ansible playbooks to define the
deployment logic. It is not based on Ironic Python Agent (IPA)
and does not generally need IPA to be running in the deploy ramdisk.
The main advantage of this deploy interface is extended flexibility in regards to changing and adapting node deployment logic for specific use cases, via Ansible tooling that is already familiar to operators.
It can be used to shorten the usual feature development cycle of
by using a “stable” deploy ramdisk and not requiring ironic-conductor restarts (see Extending playbooks).
The main disadvantage of this deploy interface is the synchronous manner
of performing deployment/cleaning tasks.
A separate ansible-playbook
process is spawned for each node being
provisioned or cleaned, which consumes one thread from the thread pool
available to the ironic-conductor
process and blocks this thread until
the node provisioning or cleaning step is finished or fails.
This has to be taken into account when planning an ironic deployment
that enables this deploy interface.
Each action (deploy, clean) is described by a single playbook with roles, which is run whole during deployment, or tag-wise during cleaning. Control of cleaning steps is through tags and auxiliary clean steps file. The playbooks for actions can be set per-node, as can the clean steps file.
Similar to deploy interfaces relying on Ironic Python Agent, this deploy
interface also depends on the deploy ramdisk calling back to ironic API’s
heartbeat
endpoint.
However, the driver is currently synchronous, so only the first heartbeat is
processed and is used as a signal to start ansible-playbook
process.
Supports whole-disk images and partition images:
For partition images the driver will create root partition, and,
if requested, ephemeral and swap partitions as set in node’s
instance_info
by the Compute service or operator.
The create partition table will be of msdos
type by default,
the node’s disk_label
capability is honored if set in node’s
instance_info
(see also Choosing the disk label).
Creating a configdrive partition is supported for both whole disk
and partition images, on both msdos
and GPT
labeled disks.
Root device hints are currently supported in their basic form only,
with exact matches (see Specifying the disk for deployment (root device hints) for more details).
If no root device hint is provided for the node, the first device returned as
part of ansible_devices
fact is used as root device to create partitions
on or write the whole disk image to.
Cleaning is supported, both automated and manual. The driver has two default clean steps:
Their priority can be overridden via
[deploy]\erase_devices_metadata_priority
and
[deploy]\erase_devices_priority
options, respectively, in the ironic
configuration file.
As in the case of this driver all cleaning steps are known to the ironic-conductor service, booting the deploy ramdisk is completely skipped when there are no cleaning steps to perform.
Note
Aborting cleaning steps is not supported.
Logging is implemented as custom Ansible callback module,
that makes use of oslo.log
and oslo.config
libraries
and can re-use logging configuration defined in the main ironic configuration
file to set logging for Ansible events, or use a separate file for this purpose.
It works best when journald
support for logging is enabled.
A set of scripts to build a suitable deploy ramdisk based on TinyCore Linux
and tinyipa
ramdisk, and an element for diskimage-builder
can be found
in ironic-staging-drivers project but will be eventually migrated to the new
ironic-python-agent-builder project.
ironic/driver-requirements.txt
fileansible
to the list of deploy interfaces defined in
[DEFAULT]\enabled_deploy_interfaces
option.ansible
deploy interface
is enabled in [DEFAULT]\enabled_hardware_types
option.[ansible]
section of ironic’s configuration
file if needed (see Configuration file).Driver options are configured in [ansible]
section of ironic
configuration file, for their descriptions and default values please see
configuration file sample.
Set them per-node via openstack baremetal node set
command,
for example:
openstack baremetal node set <node> \
--deploy-interface ansible \
--driver-info ansible_username=stack \
--driver-info ansible_key_file=/etc/ironic/id_rsa
[ansible]/default_username
option of the
ironic configuration file (defaults to ansible
).[ansible]/default_key_file
option of the
ironic configuration file.
If neither is set, the default private SSH keys of the user running
the ironic-conductor
process will be used.[ansible]/default_deploy_playbook
option of the
ironic configuration file (defaults to deploy.yaml
).[ansible]/default_shutdown_playbook
option of the
ironic configuration file (defaults to shutdown.yaml
).[ansible]/default_clean_playbook
option of the
ironic configuration file (defaults to clean.yaml
).ansible_clean_playbook
file corresponding to each cleaning step.
Default is taken from [ansible]/default_clean_steps_config
option of the
ironic configuration file (defaults to clean_steps.yaml
).[ansible]/default_python_interpreter
option of
the ironic configuration file.
Ansible uses /usr/bin/python
by default.The [ansible]\playbooks_path
option in the ironic configuration file
is expected to have a standard layout for an Ansible project with
some additions:
<playbooks_path>
|
\_ inventory
\_ add-ironic-nodes.yaml
\_ roles
\_ role1
\_ role2
\_ ...
|
\_callback_plugins
\_ ...
|
\_ library
\_ ...
The extra files relied by this driver are:
conductor ansible_connection=local
.
This basically defines an alias to localhost
.
Its purpose is to make logging for tasks performed by Ansible locally and
referencing the localhost in playbooks more intuitive.
This also suppresses warnings produced by Ansible about hosts
file
being empty.The default deploy.yaml
playbook is using several smaller roles that
correspond to particular stages of deployment process:
discover
- e.g. set root device and image targetprepare
- if needed, prepare system, for example create partitionsdeploy
- download/convert/write user image and configdriveconfigure
- post-deployment steps, e.g. installing the bootloaderSome more included roles are:
shutdown
- used to gracefully power the node off in-bandclean
- defines cleaning procedure, with each clean step defined
as separate playbook tag.Most probably you’d start experimenting like this:
deploy.yaml
playbook in the same folder,
name it distinctively.roles
folder.prepare
role
with your own one that defines steps to be run
before image download/writing.
This is a good place to set facts overriding those provided/omitted
by the driver, like ironic_partitions
or ironic_root_device
,
and create custom partitions or (software) RAIDs.configure
role
with your own one that defines steps to be run
after image is written to disk.
This is a good place for example to configure the bootloader and
add kernel options to avoid additional reboots.driver_info/ansible_deploy_playbook
field.This driver will pass the single JSON-ified extra var argument to
Ansible (as in ansible-playbook -e ..
).
Those values are then accessible in your plays as well
(some of them are optional and might not be defined):
ironic:
nodes:
- ip: "<IPADDRESS>"
name: "<NODE_UUID>"
user: "<USER ANSIBLE WILL USE>"
extra: "<COPY OF NODE's EXTRA FIELD>"
image:
url: "<URL TO FETCH THE USER IMAGE FROM>"
disk_format: "<qcow2|raw|...>"
container_format: "<bare|...>"
checksum: "<hash-algo:hashstring>"
mem_req: "<REQUIRED FREE MEMORY TO DOWNLOAD IMAGE TO RAM>"
tags: "<LIST OF IMAGE TAGS AS DEFINED IN GLANCE>"
properties: "<DICT OF IMAGE PROPERTIES AS DEFINED IN GLANCE>"
configdrive:
type: "<url|file>"
location: "<URL OR PATH ON CONDUCTOR>"
partition_info:
label: "<msdos|gpt>"
preserve_ephemeral: "<bool>"
ephemeral_format: "<FILESYSTEM TO CREATE ON EPHEMERAL PARTITION>"
partitions: "<LIST OF PARTITIONS IN FORMAT EXPECTED BY PARTED MODULE>"
ironic.nodes
add-ironic-nodes.yaml
play to populate in-memory inventory.
It also contains a copy of node’s extra
field so you can access it in
the playbooks. The Ansible’s host is set to node’s UUID.ironic.image
All fields of node’s instance_info
that start with image_
are
passed inside this variable. Some extra notes and fields:
mem_req
is calculated from image size (if available) and config
option [ansible]extra_memory
.checksum
is not in the form <hash-algo>:<hash-sum>
, hashing
algorithm is assumed to be md5
(default in Glance).validate_certs
- boolean (yes/no
) flag that turns validating
image store SSL certificate on or off (default is ‘yes’).
Governed by [ansible]image_store_insecure
option
in ironic configuration file.cafile
- custom CA bundle to use for validating image store
SSL certificate.
Takes value of [ansible]image_store_cafile
if that is defined.
Currently is not used by default playbooks, as Ansible has no way to
specify the custom CA bundle to use for single HTTPS actions,
however you can use this value in your custom playbooks to for example
upload and register this CA in the ramdisk at deploy time.client_cert
- cert file for client-side SSL authentication.
Takes value of [ansible]image_store_certfile
option if defined.
Currently is not used by default playbooks,
however you can use this value in your custom playbooks.client_key
- private key file for client-side SSL authentication.
Takes value of [ansible]image_store_keyfile
option if defined.
Currently is not used by default playbooks,
however you can use this value in your custom playbooks.ironic.partition_info.partitions
Optional. List of dictionaries defining partitions to create on the node in the form:
partitions:
- name: "<NAME OF PARTITION>"
unit: "<UNITS FOR SIZE>"
size: "<SIZE OF THE PARTITION>"
type: "<primary|extended|logical>"
align: "<ONE OF PARTED_SUPPORTED OPTIONS>"
format: "<PARTITION TYPE TO SET>"
flags:
flag_name: "<bool>"
The driver will populate this list from root_gb
, swap_mb
and
ephemeral_gb
fields of instance_info
.
The driver will also prepend the bios_grub
-labeled partition
when deploying on GPT-labeled disk,
and pre-create a 64 MiB partition for configdrive if it is set in
instance_info
.
Please read the documentation included in the ironic_parted
module’s
source for more info on the module and its arguments.
ironic.partition_info.ephemeral_format
instance_info
, it defines file system to be
created on the ephemeral partition.
Defaults to the value of [pxe]\default_ephemeral_format
option
in ironic configuration file.ironic.partition_info.preserve_ephemeral
instance_info
, it specifies if the ephemeral
partition must be preserved or rebuilt. Defaults to no
.As usual for Ansible playbooks, you also have access to standard
Ansible facts discovered by setup
module.
The provided playbooks_path/library
folder includes several custom
Ansible modules used by default implementation of deploy
and
prepare
roles.
You can use these modules in your playbooks as well.
stream_url
get_url
module in terms of
module arguments.
Due to the low level of such operation it is not idempotent.ironic_parted
parted
utility.
Due to the low level of such operation it is not idempotent.
Please read the documentation included in the module’s source
for more information about this module and its arguments.
The name is chosen so that the parted
module included in Ansible
is not shadowed.Except where otherwise noted, this document is licensed under Creative Commons Attribution 3.0 License. See all OpenStack Legal Documents.