Ansible Tower Services

One of the available catalog item types when we create a new service item is AnsibleTower (see Ansible Tower catalog item type)

Screenshot
Figure 1. Ansible Tower catalog item type


In this chapter we’ll investigate the Automate datastore components that allow us to create Ansible Tower services and service bundles that include Ansible Tower jobs.

The Ansible Tower Service Provisioning State Machine

The /ConfigurationManagement/AnsibleTower/Service/Provisioning namespace in the datastore contains the service provisioning state machines, methods and associated email classes that are required to provisioning services into Ansible Tower (see ConfigurationManagement/AnsibleTower namespace).

Screenshot
Figure 2. ConfigurationManagement/AnsibleTower namespace


The two out-of-the-box instances of the Provision state machine are default and provision_from_bundle. We use default when we’re creating a single standalone service, and provision_from_bundle when we’re running an Ansible Tower job as part of a service bundle comprising both VM provisioning and Ansible configuration operations.

The default State Machine Instance

The default state machine instance is called to process individual service catalog items. The fields of this state machine are shown in Fields of the default state machine.

Screenshot
Figure 3. Fields of the default state machine


pre1

The pre1 state calls the preprovision method, that checks whether the inputs are valid, and prints some of the input values to automation.log. It contains a useful method called modify_job_options that by default is not called (the call is commented out), but would allow us to customise any of the job options if we wished to clone and edit the method.

def modify_job_options(service)
  # Example how to programmatically modify job options:
  job_options = service.job_options
  job_options[:limit] = 'someHost'
  job_options[:extra_vars]['flavor'] = 'm1.small'

  # Important: set stack_options
  service.job_options = job_options
end
provision

The provision state calls the provision method, which performs some preliminary checking before calling the service object’s launch_job method.

checkprovisioned

The checkprovisioned state calls the check_provisioned method, which calls the service object’s job method to retrieve the ManageIQ_Providers_AnsibleTower_ConfigurationManager_Job object, and then calls the normalized_live_status job method to retrieve the current job status.

post1

The post1 state calls the post_provisioned method which allows us to perform any optional post-processing that we might deem necessary. It contains a useful method called dump_job_outputs that by default is not called (the call is commented out), but would allow us to write the job output to automation.log if required.

def dump_job_outputs(job)
  log_type = job.status == 'failed' ? 'error' : 'info'
  @handle.log(log_type, "Ansible Tower Job #{job.name} standard output: #{job.raw_stdout}")
end
EmailOwner

The EmailOwner state calls the ServiceProvision_complete email instance to notify the service requester that the service has completed.

Finished

The Finished state calls the /System/CommonMethods/StateMachineMethods/service_provision_finished instance to terminate the service provision state machine processing.

The provision_from_bundle State Machine Instance

The provision_from_bundle state machine instance is called when an Ansible service catalog item is to be called from a service bundle after a VM provisioning service catalog item. The fields of this state machine are shown in Fields of the provision_from_bundle state machine.

Screenshot
Figure 4. Fields of the provision_from_bundle state machine


As can be seen, the difference between this state machine and default is that preprovision has moved to the pre2 state, and there are new relationships in the sequencer and pre1 states to call GroupSequenceCheck and CatalogItemInitialization.

Sequencer

The Sequencer state calls the same GroupSequenceCheck instance and method that the VM provision state machines run. The GroupSequenceCheck method checks the eligibility of the current service template provisioning task to run, according to the provision order defined when the resources were added to the service bundle. GroupSequenceCheck allows the state machine to continue if all other tasks with a lower provisioning priority have a state attribute of "finished". If any of the lower priority tasks are incomplete, GroupSequenceCheck exits with a state retry and a retry interval of one minute.

The common call to GroupSequenceCheck made by both VM provisioning and AnsibleTower job state machines allows us to interleave VM provisioning service items with Ansible configuration service items. We can be sure that the Ansible configuration will not proceed until the virtual machine has been fully provisioned.

pre1

The pre1 state calls calls the same CatalogItemInitialization instance and method that the VM provision state machines run. This is to ensure that any service dialog values passed into the service bundle are available to the Ansible service template provisioning task.

Service Models

The Ansible-related service model that is of interest to us is the MiqAeServiceServiceAnsibleTower object.

MiqAeServiceServiceAnsibleTower

The MiqAeServiceServiceAnsibleTower object represents an Ansible Tower service. An object_walker printout of a typical object is as follows:

 --- attributes follow ---
 service.ancestry = nil
 service.created_at = 2016-12-01 11:11:00 UTC
 service.description = Install a Simple LAMP Stack
 service.display = true
 service.evm_owner_id = 1
 service.guid = d709ae06-b7b6-11e6-b465-001a4aa0151a
 service.id = 5
 service.miq_group_id = 2
 service.name = Simple LAMP Stack
 service.options[:dialog] = {"dialog_limit"=>"lampsrv001", "dialog_param_ntpserver"=>"192.168.xx.xx", "dialog_param_mysql_port"=>"3306", "dialog_param_dbname"=>"foodb", "dialog_param_dbuser"=>"foouser", "dialog_param_dbpass"=>"secret", "dialog_param_httpd_port"=>"80", "dialog_param_repository"=>"https://github.com/pemcg/mywebapp.git"}
 service.retired = nil
 service.retirement_last_warn = nil
 service.retirement_requester = nil
 service.retirement_state = nil
 service.retirement_warn = nil
 service.retires_on = nil
 service.service_template_id = 2
 service.tenant_id = 1
 service.type = ServiceAnsibleTower
 service.updated_at = 2016-12-01 11:11:00 UTC
 --- end of attributes ---
 --- virtual columns follow ---
 service.aggregate_all_vm_cpus = 0
 service.aggregate_all_vm_disk_count = 0
 service.aggregate_all_vm_disk_space_allocated = 0
 service.aggregate_all_vm_disk_space_used = 0
 service.aggregate_all_vm_memory = 0
 service.aggregate_all_vm_memory_on_disk = 0
 service.aggregate_direct_vm_cpus = 0
 service.aggregate_direct_vm_disk_count = 0
 service.aggregate_direct_vm_disk_space_allocated = 0
 service.aggregate_direct_vm_disk_space_used = 0
 service.aggregate_direct_vm_memory = 0
 service.aggregate_direct_vm_memory_on_disk = 0
 service.custom_1 = nil
 service.custom_2 = nil
 service.custom_3 = nil
 service.custom_4 = nil
 service.custom_5 = nil
 service.custom_6 = nil
 service.custom_7 = nil
 service.custom_8 = nil
 service.custom_9 = nil
 service.evm_owner_email = nil
 service.evm_owner_name = Administrator
 service.evm_owner_userid = admin
 service.has_parent = false
 service.owned_by_current_ldap_group = nil
 service.owned_by_current_user = nil
 service.owning_ldap_group = EvmGroup-super_administrator
 service.power_state = nil
 service.power_status = nil
 service.region_description = Region 0
 service.region_number = 0
 service.service_id = nil
 service.v_total_vms = 0
 --- end of virtual columns ---
 --- associations follow ---
 service.all_service_children
 service.direct_service_children
 service.direct_vms
 service.indirect_service_children
 service.indirect_vms
 service.parent_service
 service.root_service
 service.service_resources
 service.service_template
 service.tenant
 service.vms
 --- end of associations ---
 --- methods follow ---
 service.automate_retirement_entrypoint
 service.configuration_manager
 service.custom_get
 service.custom_keys
 service.custom_set
 service.description=
 service.dialog_options
 service.display=
 service.error_retiring?
 service.extend_retires_on
 service.finish_retirement
 service.get_dialog_option
 service.group=
 service.inspect
 service.inspect_all
 service.job
 service.job_options
 service.job_options=
 service.job_template
 service.job_template=
 service.launch_job
 service.model_suffix
 service.name=
 service.owner=
 service.parent_service=
 service.reload
 service.remove_from_vmdb
 service.retire_now
 service.retire_service_resources
 service.retired?
 service.retirement_state=
 service.retirement_warn=
 service.retires_on=
 service.retiring?
 service.set_dialog_option
 service.shutdown_guest
 service.start
 service.start_retirement
 service.stop
 service.suspend
 service.tag_assign
 service.tag_unassign
 service.tagged_with?
 service.tags
 --- end of methods ---

The object is an extension of the standard MiqAeServiceService object type, but adds several useful Ansible-specific methods, as follows:

 service.configuration_manager
 service.job
 service.job_options
 service.job_options=
 service.job_template
 service.job_template=
 service.launch_job

It is the launch_job method that is called during the state machine provision state to initiate the running of the Ansible Tower job.

Summary

The chapter has completed our examination of the Tower-related components in the Automate datastore that we started in Tower Related Automate Components. The state machines, instances and methods that we’ve studied here are used when we create services to deploy Ansible configuration scripts.

In the next chapter we’ll run through two examples of creating Ansible Tower services; one for a single catalog item, and another as part of a catalog bundle.

results matching ""

    No results matching ""