How do I add hosts from provisioned vms to Ansible Tower Inventory?

automate

#1

Hi, I’m having a problem with adding new hosts to Ansible inventory. I would like that if a new vm is provisioned to get added automatically to Ansible Tower Inventory. I tried creating a button on Cloudforms where I manually add the hosts to the inventory but it did not work.

--
- hosts: all
  vars:
    pubkey: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDxfW4mLwlZRoUV3aGY8QC5/1Mg+uSa1Sko/KmTwe3U+gc269x0lwFV+EhbTeYmk7a9k2jRwSMcnHnsYtGvyeMImJL0heR6OwGy2FYyT/HpQ3bDPUtEZRXvT5bsDd9uXJox0ijnyeP6TExJw0zV7CzggMIW4e3nt0Yh68pHWGo6y62XWgIJProBJco3FeB6ZDOapKFdiLug7XK2pKfO4t00iCIplfeNhtgPErPyVQiKJFaHwYvqP3aEW9L5qFYLVPJQ2c68sqNq++fulwIvpXUd4KzHtpHhNi2bXxxPShpjFg4QJTzsE4JD/SH/v9TLMDpbk7w7ZEVyVvOi2BVflOJl root@iaas.mypfeproject.tn'
  host_key_checking = False
  tasks:
  - name: make direcotry
    file:
      path: "/home/{{ vm_user }}/.ssh"
      state: directory
  - name: create empty file
    file:
      path: "/home/{{ vm_user }}/.ssh/authorized_keys"
      state: touch
  - name: put pubkey
    lineinfile:
      path: "/home/{{ vm_user }}/.ssh/authorized_keys"
      line: "{{ pubkey }}"
  - name: add hosts to inventory
    lineinfile:
    path: "root@rhevm.example.com:/etc/ansible/hosts"
    line: "{{ hosts }}"
  - name: ensure ssh is running (and enable it at boot)
    service:
      name: httpd
      state: started
      enabled: yes

As you can see here, I tried to manually echo the new host to the inventory but it did not work, it just stopped in the middle of establishing the connection. I also tried to follow a tutorial on how to add dynamic inventory using this script and I did put cloudforms.ini under /etc/ansible/cloudforms.ini. See Ansible - Cloudforms.py
. But the Job always ends up with a failure saying that
RuntimeError: ansible-inventory failed (rc=1) with stdout: stderr: [WARNING]: * Failed to parse /tmp/awx_inventory_uBsfcr/tmpbA1sY1 with script plugin: Inventory script (/tmp/awx_inventory_uBsfcr/tmpbA1sY1) had an execution....

Is there any other way that could add my hosts to Ansible Inventory?
PS: in the ssh command I tried to add my host to the inventory I had in my rhevm machine but I did not try to add it to Ansible tower Inventory, Since it was using that inventory.


#2

In Tower you can add MIQ/CF as inventory source, so Tower will sync itself.


#3

and how do I do that? I tried with inventory scripts and it did not work for me.


#4

See Inventories .


#5

I tried your solution but I still get this error:

1.969 INFO     Updating inventory 3: CloudForms VMs
2.219 INFO     Reading Ansible inventory source: /var/lib/awx/venv/awx/lib/python2.7/site-packages/awx/plugins/inventory/cloudforms.py
Traceback (most recent call last):
  File "/usr/bin/awx-manage", line 9, in <module>
load_entry_point('awx==3.2.3', 'console_scripts', 'awx-manage')()
  File "/lib/python2.7/site-packages/awx/__init__.py", line 107, in manage
  File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/__init__.py", line 354, in execute_from_command_line
utility.execute()
  File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/__init__.py", line 346, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/base.py", line 394, in run_from_argv
self.execute(*args, **cmd_options)
  File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/base.py", line 445, in execute
output = self.handle(*args, **options)
  File "/var/lib/awx/venv/awx/lib/python2.7/site-packages/django/core/management/base.py", line 661, in handle
return self.handle_noargs(**options)
  File "/lib/python2.7/site-packages/awx/main/management/commands/inventory_import.py", line 995, in handle_noargs
  File "/lib/python2.7/site-packages/awx/main/management/commands/inventory_import.py", line 245, in load_inventory_source
  File "/lib/python2.7/site-packages/awx/main/management/commands/inventory_import.py", line 180, in load
  File "/lib/python2.7/site-packages/awx/main/management/commands/inventory_import.py", line 163, in command_to_json
RuntimeError: ansible-inventory failed (rc=1) with stdout:

stderr:
 [WARNING]:  * Failed to parse /var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/cloudforms.py with script plugin: Inventory
script (/var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/cloudforms.py) had an execution error: Traceback
(most recent call last):   File "/var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/cloudforms.py", line 461, in <module>
CloudFormsInventory()   File "/var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/cloudforms.py", line 55, in __init__
self.update_cache()   File "/var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/cloudforms.py", line 282, in update_cache
for host in self._get_hosts():   File "/var/lib/awx/venv/awx/lib/python2.7
/site-packages/awx/plugins/inventory/cloudforms.py", line 264, in _get_hosts
ret = self._get_json("%s/api/vms?offset=%s&limit=%s&expand=resources,tags,hosts
,&attributes=ipaddresses" % (self.cloudforms_url, offset, limit))   File
"/var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/cloudforms.py", line 230, in _get_json
verify=self.cloudforms_ssl_verify)   File
"/var/lib/awx/venv/ansible/lib/python2.7/site-packages/requests/api.py", line
72, in get     return request('get', url, params=params, **kwargs)   File
"/var/lib/awx/venv/ansible/lib/python2.7/site-packages/requests/api.py", line
58, in request     return session.request(method=method, url=url, **kwargs)
File "/var/lib/awx/venv/ansible/lib/python2.7/site-
packages/requests/sessions.py", line 504, in request     prep =
self.prepare_request(req)   File "/var/lib/awx/venv/ansible/lib/python2.7/site-
packages/requests/sessions.py", line 436, in prepare_request
hooks=merge_hooks(request.hooks, self.hooks),   File
"/var/lib/awx/venv/ansible/lib/python2.7/site-packages/requests/models.py",
line 302, in prepare     self.prepare_url(url, params)   File
"/var/lib/awx/venv/ansible/lib/python2.7/site-packages/requests/models.py",
line 382, in prepare_url     raise MissingSchema(error)
requests.exceptions.MissingSchema: Invalid URL '192.168.2.55/api/vms?offset=0&l
imit=100&expand=resources,tags,hosts,&attributes=ipaddresses': No schema
supplied. Perhaps you meant http://192.168.2.55/api/vms?offset=0&limit=100&expa
nd=resources,tags,hosts,&attributes=ipaddresses?

 [WARNING]:  * Failed to parse /var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/cloudforms.py with ini plugin:
/var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/cloudforms.py:23: Expected key=value host
variable assignment, got: __future__

 [WARNING]: Unable to parse /var/lib/awx/venv/awx/lib/python2.7/site-
packages/awx/plugins/inventory/cloudforms.py as an inventory source

ERROR! No inventory was parsed, please check your configuration and options.

#6

The URL of the CF credential (in Tower) should start with https://

The error message above says the URL is wrong:
Invalid URL '192.168.2.55/api/vms?offset=0&limit=100&expand=resources,tags,hosts,&attributes=ipaddresses': No schema supplied. Perhaps you meant http://192.168.2.55/api/vms?offset=0&limit=100&expand=resources,tags,hosts,&attributes=ipaddresses?


#7

Thank you for pointing that out, I fixed the url but It’s now only showing the powered on vms, Now I tried to add another source to add the list of vms on my rhev and it worked thank you so much. I didn’t notice that I have put in the wrong url :woman_facepalming:


#8

HI Guys. I have a caveat about Ansible Tower dynamic inventory logic. Only one run at a time of this inventory can be. So if you have multiply provisions of virtual machines only one can be processed all others will be wait in queue.
I recommend to use API call to Ansible Tower to create host in inventory. This call you can create as a step in vm provisioning state machine.
In this way multiple provisions will proceed simultaneously.


#9

is there a tutorial or a guide I can follow? I’m really new to Ansible Tower.


#10

Could you provide steps for doing this through APIs call


#11

@coolpalani @miiraheart

Hi Guys.

I am using OpenStack provider and provision workflow for such cloud instances have openstack_postprovision method. By default this method does not have any usable code:

I have created override for this method:

So during postprovision phase I am creating host in Ansible Tower inventory and populate host variables based on CFME attributes of provisioned instance.

For retirement workflow I have paired method which is removes host from inventory.

Next step you should create additional step in VM provision state machine to run Ansible Tower Job Template. The good description of such task is Peters book:
https://pemcg.gitbooks.io/mastering-automation-in-cloudforms-4-2-and-manage/content/automation_using_ansible/chapter.html


#12

@xian & @igortiunov Can I modify this method in order to get the second ip for vms. My problem is that every vm have 2 ip addresses, one default which is 192.168.122.1 (virbr0) ( I honestly don’t know how they got this ip maybe from Cloudforms) and the other one is the static ip address. When I run my playbook and limit it to specific host it just uses the 192.168.122.1 so Im affraid that it will run the playbook on all vms, How do fix this?


#13

Line 160:

variables['ansible_host'] = vm.ipaddresses[1]

What is your provider? OpenStack? Not sure where this virbr0 coming from, should not…


#14

I’m using Cloudforms does this method work just fine with it. Yeah all vms have both eth0 which is static and virbr0 (default) which 192.168.122.1. I don’t want to disable it maybe it will mess the environment, maybe cloudforms uses it or rhevm


#15

You can check attributes of your VMs by Object Walker:

Generic vm have fixed_ip_adderess attribute, may be it what you want.


#16

Does changing variables['ansible_host'] = vm.ipaddresses[1] in the method you provided will work if I switched the postprovision method on Cloudforms and get Ansible Tower to use the second ip address?


#17

May be, but I think you can change the script to be more readable for you. Check the attributes of your vm (RHEV provider ?) and change vm.ipaddresses[1] to corresponding one:

or


#18

I have fixed this issue by following this From Red Hat and by disabling libvirtd
systemctl disable libvirtd.service and rebooting the vm, the default interface virbr0 have been disabled and now I can run my job templates.