Ansible Playbook Methods
Last updated
Last updated
CloudForms 4.6 / ManageIQ Gaprindashvili has introduced the capability to run Ansible playbooks as automation methods. It is now possible to mix Ruby and/or Ansible methods in a single state machine or instance.
A playbook method is created in the same way as other automate methods. CloudForms 4.6 (ManageIQ Gaprindashvili) has added two more method types, one of which is playbook (see screenshot Adding a New Playbook Method)
Once the method Type of playbook has been selected the method definition page appears, which contains the same input options as the Provisioning tab when creating a playbook service (see section Provisioning Tab Options).
For a playbook method a value for Max TTL (mins) should always be entered; a running playbook will be terminated after this time. In CFME 5.9.3 the default is 0 minutes.
For playbooks running in a state machine, a retrying state's ae_retry_interval
is calculated from the Max TTL divided by the ae_state_max_retries
value, as long as neither is zero (the minimum ae_retry_interval
in this case being 60 seconds).
Note
If Update on Launch is checked in the repository definition, the time taken to refresh the repository is included in the Max TTL duration.
The Hosts input dialog has two options: Localhost or Specify host values. In many cases we would wish to run the playbook on the CFME or ManageIQ appliance itself, so Localhost should be selected. In other cases we might wish to run a playbook on a managed node as part of a workflow - such as a VM provision - in which case the hostname or IP address might not be known at the time that the playbook method is created.
Fortunately we can use the automation engine's substitution syntax in the Hosts dialog. This allows us to specify an attribute that at run-time would contain the valid value for a managed node's IPv4 address or fully-qualified domain name. An example might be ${/#miq_provision.destination.ipaddresses.first}
for an infrastructure VM provision, or ${/#miq_provision.destination.floating_ip_addresses.first}
for a cloud instance provision (see screenshot Substitution Variable as a Host Value).
Note
When using the substituted value of the target host's IP address in this way in a VM provisioning workflow, it may be necessary to add a wait_for_ip stage in the workflow to give the newly provisioned VM time to boot and get an IP address. The out-of-the-box /AutomationManagement/AnsibleTower/Operations/StateMachines/Job/wait_for_ip method can be used for this purpose.
The Input Parameters section of the playbook method creation page allows us to add variables that will be made available to the playbook at run-time. This corresponds to the Variables & Default Values section when creating a playbook service, but unlike when creating a playbook service, the Input Parameters can take the form of automation engine substitution strings (see screenshot Input Parameters).
Input parameters can be of the same data types permissable for an automation datastore class schema attribute. Some complex data types can be passed, for example the data type of array allows for comma-separated lists of values to be supplied. Hashes can be encoded as strings (see screenshot Passing Complex Data Types).
Input parameters such as these can be examined from the playbook, for example:
When used with debug
in this way the following output is printed:
When an Ansible playbook is run as an Automate method, a number of manageiq-specific variables are made available to the playbook to use in addition to the input parameters. These are similar to the variables available to a playbook service, but with the addition of the automate_workspace variable that allows the playbook to interact with the $evm
workspace managing the automation workflow.
The Automate workspace is a memory region containing all objects associated with an automation workflow. In a Ruby-based workflow the workspace is called $evm
. As the workflow progresses any objects that are created or accessed are loaded into the workspace, and the workspace is destroyed once the workflow is complete. A workspace is private to an individual workflow; concurrent workflows have no access to each other's workspaces for security reasons.
A workspace can be accessed and edited - with suitable credentials - by an Ansible paybook using the RESTful API. The capability to interact with the Automate workspace, much like a Ruby automate method, increases the versatility of Ansible playbook methods and allows Ruby and Ansible methods to be mixed in the same state machines or workflows.
A typical json content of an Automate workspace as retrieved by a playbook is as follows:
As can be seen, all of the workspace variables that are typically accessed fom a Ruby method - for example $evm.root
attributes such as ae_state_retries
- are also available from an Ansible playbook method.
The manageiq-automate
role (see section manageiq-automate) allows an Ansible playbook to interact with the workspace. The role provides the following modules:
object_exists
attribute_exists
state_var_exists
method_parameter_exists
get_attribute
get_decrypted_attribute
get_vmdb_object
get_object_names
get_object_attribute_names
get_state_var_names
get_method_parameter
get_decrypted_method_parameter
get_method_parameters
set_attribute
set_encrypted_attribute
set_attributes
set_retry
get_state_var
set_state_var
As with 'traditional' Ruby-based automation, values can be saved to and restored from the $evm
workspace, and used in subsequent stages of a workflow.
For a simple instance schema containing one or more Ansible playbook methods interspersed with one or more Ruby methods, values can be passed as $evm.root
or $evm.object
attributes. This can be illustrated with a simple playbook that uses the manageiq-automate
role to read a dialog value from $evm.root
, and store the tower_job_id
value back into the workspace, as follows:
The saved tower_job_id
value can be read from $evm.root
by a Ruby method, and used to lookup the output of the Ansible playbook, as follows:
Attribute values in $evm.root
or $evm.object
in a state machine are not saved if any state triggers a retry. In this scenario state variables should be used to store values between state machine retries, and these can be written and read from both Ansible playbook and Ruby methods.
This can be illustrated with the following two state machine methods. The first (Ruby) method writes a simple state variable containing the current time, as follows:
The second (Ansible playbook) method retrieves the saved state variable using the manageiq-automate
role, as follows:
In this example the playbook method simply prints the output using a debug
task. The debug output line showing a typical retrieved state variable is as follows:
Running an Ansible playbook is an asynchronous operation for the automation engine, with an indeterminate run-time. If an Ansible playbook method is used in a state machine, the state running the playbook is put into an immediate retry condition, without the on_exit
method being run. When the playbook completes the state machine continues.
One implication of this behaviour is that if a state machine containing a playbook method is run from Automation -> Automate -> Simulation in the WebUI, the state retry must be manually committed using the Retry button for the playbook's state to complete (see screenshot Simulation Retry Button).
A playbook can also trigger its own state retry, as follows:
The run status of a playbook method can be checked in the WebUI under Tasks -> All Tasks under the user's menu (see screenshot Playbook Task Status).
The playbook's output is not available from this page however; it must be viewed directly from the job's /var/lib/awx/job_status/*.out log file or from evm.log if Logging Output was defined for the method.
This chapter has introduced Ansible playbook methods, which are a powerful new feature of CloudForms 4.6 (ManageIQ Gaprindashvili). They can be used anywhere that a 'traditional' Ruby Automate method can be used, but they require no Ruby knowledge to implement.
The next chapter will show how Ansible playbook methods can be used together with Ruby methods in a VM Provisioning state machine.