Satellite and Ansible Tower Integration

Using Red Hat Satellite and Red Hat Ansible Automation Platform? Starting with Satellite 6.3, they can be integrated with each other so that Dynamic Inventory in Ansible Tower pulls up host lists from Satellite. In addition, if the RHEL hosts are initialized using Satellite (meaning provisioning), then Ansible Tower can be integrated into this process so that it automatically runs configuration scripts on the new hosts.



In this post, we will look at how to configure Dynamic Inventory in Ansible Tower so that it pulls up the hosts from Satellite, and we will show how to use it with examples. In addition, we’ll show you how to organize an automatic call to Ansible Tower after initializing a new host from Satellite.

1. Inventory. Satellite, Dynamic Inventory Ansible Tower


For Ansible Tower to have access to the list of hosts, host groups, and other related information, it needs an account in Satellite. This entry has enough minimal permissions, so we will create a new role in Satellite, give it only the permissions necessary for Ansible Tower, and then create a new account and assign it this role.

Satellite 6.6 and later already has an Ansible Tower Inventory Reader role ready for this, so you can skip the steps below to create a role.

In Satellite 6.3-6.5, the role will have to be created by hand. To do this, go to the Satellite web interface, go to the Administer screen, select Roles and click Create Role.

We name this role ansible_tower_integration_role and set Locations and Organizations for it :



Click Submit to create the role. After that, click on her name and go to the Filters tab. Click the green New Filter button and add the following filters, one at a time:

Resource Type: Host , Permission: view_hosts
Resource Type: Host Group , Permission: view_hostgroups
Resource Type: Fact value , Permission: view_facts

As a result, the following filters should have a role:



So, we have created a role. Now we’ll start a new user in Satellite, for which we go to the Administer menu , select Users and click Create User . We name this user ansible_integration , change the Authorized by parameter to INTERNAL and set the password. Then on the Locations and Organizations tabs, select the appropriate locations / organizations. Finally, go to the Roles tab and assign this user the newly created ansible_tower_integration_role role (if you have Satellite 6.3 - 6.5) or the built-in Ansible Tower Inventory Reader role(Satellite 6.6 and higher). Finally, click Submit to create an account for this user.

Customize Ansible Tower


Now go to the Ansible Tower web interface and go to the Credentials screen . Click the green + (Add) button to create a new Credential entry. We call it satellite_integration , and in the Credential Type we specify Red Hat Satellite 6 . Then we enter the URL (in our case Satellite 6), as well as the username (in our case ansible_integration ), and the password is the one that we set in Satellite above:



Then click Save .

Now go to the Inventories screen , click the green + (Add) button and select Inventory . Specify satellite_inventory as the name and click Save to create an inventory. After that, go to the Sources tab of the newly created inventory and click the green + (Add) button . We use satellite as the source name , and specify the source type as Red Hat Satellite 6 . In the Credential field, specify satellite_integration , which was created in the previous step. Turn on the Overwrite checkbox ,Overwrite Variables and Update on Launch in the Update Options control group (you can learn more about these options using the question marks on the right). In addition, in the Cache Timeout (Seconds) field, enter 90 and click Save .



Now, without leaving the Sources tab , click the Start sync process icon :



We wait until the icon turns green - this signals a successful completion of synchronization.

Now you can go to the Hosts tab and see the data that has been pulled from the Satellite:



You can also look at the Groups tab:



As you can see, synchronization not only pulled up the host lists from Satellite, but also divided them into groups according to the corresponding content views in Satellite, host groups, lifecycle environments, locations and organizations. This grouping can be used to target Ansible scripts on target hosts, and this is a very powerful thing.

If you select a host on the Hosts tab, we will see that between Satellite and Ansible Tower a lot of auxiliary information about the host is synchronized, which is presented in the form of variables. These variables can then be used in Ansible scripts:



Using Dynamic Inventory Tied to Satellite


So, we synchronized Satellite and Ansible Tower. Now we will consider how to use it in practice.

The easiest way is to use satellite_inventory as the Inventory source in the Ansible Tower Template. If the hosts: all option is specified in the script , the script will be run on all Satellite hosts.

A more advanced option is to use automatically created inventory groups in scripts (how they are created - see above), in other words, specify the desired host group in the hosts line . For example, as in this scenario where the screen package is installed:

---
- name: Install screen package
  hosts: "foreman_hostgroup_rhel6"
  tasks:
  - yum:
      name: screen
      state: installed

Here we have registered hosts: foreman_hostgroup_rhel6 , thereby indicating the list of hosts forming the rhel6 host group in the Satellite. Accordingly, the script will be executed only on these hosts.

In addition, in the script, you can specify in the hosts line those variables that Ansible Tower receives during synchronization with Satellite. For example, you can do this:

---
- name: Install screen package
  hosts: "{{ hosts_var }}"
  tasks:
  - yum:
      name: screen
      state: installed

As a result, we will be able to change the job template in Ansible Tower on the fly, indicating one of the inventory groups through an external variable.



In this example, the template will only run on hosts that are members of the rhel7 group in Satellite.

Moreover, the job template can be configured so that at startup it will ask the user for the value of the hosts_var variable (and at the same time display the available inventory groups in the form of comments):



The screen above illustrates the situation when, when the template is launched, the user is prompted to enter the name of the Satellite inventory group on whose hosts you want to run the script.

In addition, you can use the host variables pulled from Satellite during synchronization. For example, here's what a script looks like showing how to reference these variables:

---
- name: Show Satellite variables
  hosts: all
  tasks:
  - name: Show subscription_status
    debug:
      msg: >
        Subscription Status: {{ foreman.subscription_status_label }}
  - name: Show Errata Counts
    debug:
      msg: >
        Bug fixes: {{ foreman.content_facet_attributes.errata_counts.bugfix }},
        Security: {{ foreman.content_facet_attributes.errata_counts.security }},
        Enhancement: {{ foreman.content_facet_attributes.errata_counts.enhancement }},
        Total: {{ foreman.content_facet_attributes.errata_counts.total }}

If you run this script in Ansible Tower, it will show the values ​​of the variables:



And of course, these variables can be used in conditional constructions when, so that tasks are launched only under certain conditions. For example, if the host does not have security patches, or when the host subscription is invalid.

To summarize


Red Hat Satellite and Red Hat Ansible themselves are very powerful tools, and their integration provides tangible synergy. Above, we showed how to make Satellite a data source for Dynamic Inventory in Ansible and use it in practice.

Part 2. Autoconfiguration of new hosts through provisioning callback


In addition to many other features, Satellite is also able to initialize hosts, in other words, perform provisioning. Ansible Tower, in turn, is designed to configure hosts. Integration allows you to make sure that after the initialization of a new RHEL host by means of Satellite, Ansible Tower will automatically connect to this host and run the corresponding configuration script on it. Obviously, such a scheme saves a lot of time for system administrators, helping them to respond more quickly to the needs of the organization.

It should be noted that this scheme only works if several conditions are met. First, Satellite should be used as a Dynamic Inventory data source in Ansible Tower (we covered this issue in the previous part). Secondly, host initialization should not only be done through Satellite, but also work through the host group mechanism (for more details, see the Provisioning Guide ).

Below we show how to configure Satellite and Ansible Tower so that after initializing the host, it will automatically run the Ansible configuration script.

Overview


IT automation tools, such as Ansible Tower, usually fall into one of two categories: some work by the push method, others by the pull method. In push systems to which Ansible Tower belongs, the automation server initiates a connection to the host. In pull systems, the initiator is the host, which itself communicates with the automation server.

In our case, with automatic scripting on new hosts, a mixed scheme is used. The newly initialized host contacts the automation server with a request to “call back” to it and configure. After that, the automation server connects to this host and runs the configuration script requested by the host on it. Therefore, in Ansible Tower this mechanism is called provisioning callback, which can be translated as “initialization callback”.

To show why provisioning callback is needed at all, consider the following situation: we have a certain host configuration script that runs daily at midnight. Let's say at 8 a.m. we are initializing several new servers at once through Satellite. At the same time, Satellite is used as a Dynamic Inventory data source in Ansible Tower, so the created hosts automatically fall into Ansible. However, the next launch of the automation script will take place only at midnight, that is, after 16 hours. Obviously, this is far from ideal, and I would like the script to run immediately after the initialization of the new host. For this purpose provisioning callback is also thought up.

In general, provisioning callback is configured and works as follows:

  1. Ansible Tower credential root, Satellite . Tower , .
  2. Job Template Ansible Tower provisioning callback. URL Host Config Key, Ansible.
  3. Satellite , provisioning callback Ansible Tower, : URL- Ansible Tower, Host Config Key Ansible.
  4. Satellite /etc/systemd/system/ansible-callback.service ( RHEL 7 8; RHEL 6 ). provisioning callback Ansible Tower, , (URL-, Host Config Key ).
  5. Ansible Tower Host Config Key. , Tower , root, Job Template. , .

Ansible Tower Provisioning Callback


Let's start by creating a configuration script on the Ansible Tower server that changes the contents of / etc / motd, creates some kind of user, and installs a specific package. Then we will use this script to configure new hosts immediately after they are initialized.

In real life, automation scripts are most likely stored in some version control system, but for simplicity, we assume that they lie directly on the Ansible Tower server. Therefore, we enter the Ansible Tower server via SSH and create the directory / var / lib / awx / projects / provision for them by running the following command:

# mkdir /var/lib/awx/projects/provision

Then we create our script in this directory, call it provision.yaml and write the following contents into it:

---

- name: Provision new host

  hosts: all

  tasks:

  - name: Set content in /etc/motd 

    copy:

      content: Authorized use only!

      dest: /etc/motd

      mode: 644

      owner: root

      group: root


  - name: Create brian user account

    user:

      name: brian

      uid: 10000

      state: present


  - name: Install tmux package

    yum:

      name: tmux

      state: present


Now go to the Tower web interface and go to the Credentials screen. We click the button with the green plus sign to create a new credential record, give it the name provisioning_root, and also set the Credential Type as Machine. In the Username field, write root, and in the Password field, specify the password that is specified in Satellite for use on the new hosts of the corresponding host group in Satellite (its name can be found in the Satellite web interface on the Operating System tab). Using this entry, Ansible Tower will be able to log in to new hosts created during initialization via Satellite.



After that, in the Ansible Tower interface, go to the Projects screen and click the green plus sign to create a new project. Call it provision, change SCM Type to Manual, and specify provision as the Playbook Directory:



Then, in the Ansible Tower interface, go to the Templates screen, click the green plus sign to create a new Job Template. We will call it provision, in the Inventory field we will write Satellite, in the Project field - provision, in the Playbook field - provision.yaml, and in the Credential field - provisioning_root. In addition, you need to enable the Allow Provisioning Callbacks checkbox and click the magic wand icon to the right of the Host Config Key field to generate a secret key. This key is needed in order to request a provisioning callback could not be anyone, but only someone who knows the Host Config Key. Without the correct key, the Ansible Tower server simply will not respond to the request.



Now we need to remember for the future the value of the Host Config Key, as well as the Template ID, which can be found from the URL of this Job Template:

https://tower.example.com/#/templates/job_template/11

In this example, the ID is 11.

Configuring Satellite for Provisioning Callback


Now go to the satellite web interface, go to the Configure screen and click Host Groups. We select the existing host group, which is used when initializing new hosts, in our example, this is RHEL 8.

On the host group editing screen, go to the Parameters tab and create 4 new parameters:

ansible_host_config_key - here we enter Host Config Key from our Ansible Tower Template.
ansible_job_template_id - here we write the Template ID, which we previously found out from the template URL.
ansible_tower_fqdn is the fully qualified domain name of the Ansible Tower server.
ansible_tower_provisioning - set true.



Check how everything works


Now initialize the new host from Satellite and verify that the provisioning callback works and automatically runs our script on that host.

In the Satellite web interface, go to the Hosts screen, click Create Host and verify that the group for which we just created 4 new parameters is used, that is, the RHEL 8 group.



After the host initialization is complete, we need to make sure that the template on it has been successfully launched. To do this, go to the Templates screen in the Ansible Tower web interface, look for our template in the list and see if the leftmost square of its indicator turns green:



We click this green box to see the launch details, which in our case was successful. Please note that this task has a limit (Limit) - the launch of only new hosts that are created during initialization. Well, this is not surprising, since the provisioning callback mechanism only runs the template on those hosts that request it.



Now let's go to the newly created host and check if it matches what is written in the script:

[root@provision-test-rhel8 ~]# rpm -qa | grep tmux
tmux-2.7-1.el8.x86_64

[root@provision-test-rhel8 ~]# id brian
uid=10000(brian) gid=10000(brian) groups=10000(brian)

[root@provision-test-rhel8 ~]# cat /etc/motd
Authorized use only!

Troubleshooting


If the Ansible Tower template does not start automatically on a new host initialized via Satellite, there are a few things to check.

The first step is to find out if the Ansible Tower received a request for a provisioning callback, how the script ran and whether it started at all. To do this, in the Tower interface, go to the Templates screen and look at the color of the indicator next to the template name: green - the launch was successful, red - the launch failed.



If the box is red, then we click it and look for additional information to understand why the launch failed (these can be both syntax errors in the script and other problems).

If the square is green, then we click and look anyway, since the task could report successful execution, but it did not actually start on our host. For example, if the hosts line in the script indicates specific hosts and groups, but does not include the hosts created during initialization, the task will report success, but the additional information will say “skipping: no hosts matched”.

If the indicator square is neither green nor red, then you need to start by checking the parameters of the host group in Satellite. Make sure the Ansible Tower server URL, Host Config Key, and template ID are correctly specified there.

Next, go to the newly initialized host and check that there is a file /etc/systemd/system/ansible-callback.service (on RHEL 7 or 8 systems) or a file /root/ansible_provisioning_call.sh (RHEL 6).

If the file does not exist, verify that the ansible_tower_provisioning parameter is set to true for this host group, and that the initialization patterns on the Satellite server have not been changed.
If the file /etc/systemd/system/ansible-callback.service is present on the host, then open it and look for the URL where the provisioning callback request is sent:

[root@provision-test-rhel8 ~]# cat /etc/systemd/system/ansible-callback.service
[Unit]
Description=Provisioning callback to Ansible Tower
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/curl -k -s --data "host_config_key=aa5ebe82-491c-4fbb-bd36-a6657549451e" https://tower.example.com/api/v2/job_templates/11/callback/
ExecStartPost=/usr/bin/systemctl disable ansible-callback

[Install]
WantedBy=multi-user.target

You can run curl and manually duplicate the commands specified in this file to manually initiate a provisioning callback:

[root@provision-test-rhel8 ~]# /usr/bin/curl -k -s --data "host_config_key=aa5ebe82-491c-4fbb-bd36-a6657549451e" https://tower.example.com/api/v2/job_templates/11/callback/

If an invalid Host Config Key is specified, we will receive the following error message:

[root@provision-test-rhel8 ~]# /usr/bin/curl -k -s --data "host_config_key=wrong-key-here" https://tower.example.com/api/v2/job_templates/11/callback/

{"detail":"You do not have permission to perform this action."}

If the Template ID is incorrectly specified (here - 43 instead of 11), then the answer will be as follows:

[root@provision-test-rhel8 ~]# /usr/bin/curl -k -s --data "host_config_key=wrong-key-here" https://tower.example.com/api/v2/job_templates/43/callback/

{"detail":"Not found."}

You can also disable silent (-s) mode in the curl command so that it displays errors related to resolving the host name, as in the example below, where we replaced the correct name ansible.example.com with the incorrect ansible-tower.example.com :

[root@provision-test-rhel8 ~]# /usr/bin/curl -k  --data "host_config_key=wrong-key-here" https://ansible-tower.example.com/api/v2/job_templates/11/callback/

curl: (6) Could not resolve host: ansible-tower.example.com

In addition, when finding out the cause of the error, the /var/log/tower/tower.log file on the Ansible Tower server may come in handy.
For example, this file records the use of an invalid Host Config Key:

2019-11-19 23:19:17,371 WARNING  awx.api.generics status 403 received by user AnonymousUser attempting to access /api/v2/job_templates/11/callback/ from 192.168.0.138

This also fixes the use of an invalid Template ID:

2019-11-19 23:19:49,093 WARNING  awx.api.generics status 404 received by user AnonymousUser attempting to access /api/v2/job_templates/43/callback/ from 192.168.0.138

2019-11-19 23:19:49,095 WARNING  django.request Not Found: /api/v2/job_templates/43/callback/

To summarize


The integration of Satellite and Ansible Tower can greatly optimize the initialization and configuration of new hosts, which saves a lot of time for system administrators, helping them to respond more quickly to the needs of the organization.

On March 24, from 11:00 to 12:30 Red Hat will hold a webinar “What You Need to Know About Automation: Basic Ansible Skills”

Automation is a topic approaching in popularity and the number of requests for digital transformation. We will tell you about our view of automation - along with Ansible and Ansible Tower - and this will be the basic information that will open you the door to the brave new world of declarative automation tools.
After this webinar, you will understand the basic Ansible entities, such as playbook, inventory, module. Together with you, we will master the basic YAML syntax so that you can write your own scripts. It will also consider launching scripts and escalating privileges.

As a result, you will get a basic set of skills that will allow you to successfully study documentation and other literature without the constant feeling that you are missing something. Register and come!

All Articles