Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set SSH Host IP Address on Rackspace for Ansible

The Question

When using the rax module to spin up servers and get inventory, how do I tell Ansible to connect to the IP address on an isolated network rather than the server's public IP?

Note: Ansible is being run from a server on the same isolated network.

The Problem

I spin up a server in the Rackspace Cloud using Ansible with the rax module, and I add it to an isolated/private network. I then add it to inventory and begin configuring it. The first thing I do is lock down SSH, in part by telling it to bind only to the IP address given to the host on the isolated network. The catch is, that means ansible can't connect over the public IP address, so I also set ansible_ssh_host to the private IP. (This happens when I add the host to inventory.)

- name: Add servers to group
  local_action:
    module: add_host
    hostname: "{{ item.name }}"
    ansible_ssh_host: "{{ item.rax.addresses.my_network_name[0].addr }}"
    groups: launched
  with_items: rax_response.success
  when: rax_response.action = 'create'

This works just fine on that first run of creating and configuring new instances. Unfortunately, the next time I try to connect to these servers, the connection is refused because Ansible is trying at an IP address on which SSH isn't listening. This happens because:

  1. Ansible tries to connect to ansible_ssh_host...
  2. But the rax.py inventory script has set ansible_ssh_host to the accessIPv4 returned by Rackspace...
  3. And Rackspace has set accessIPv4 to the public IP address of the server.

Now, I'm not sure what to do about this. Rackspace does allow an API call to update a server and set its accessIPv4, so I thought I could run another local_action after creating the server to do that. Unfortunately, the rax module doesn't appear to allow updating a server, and even if it did it depends on pyrax which in turn depends on novaclient, and novaclient only allows updating the name of the server, not accessIPv4.

Surely someone has done this before. What is the right way to tell Ansible to connect on the isolated network when getting dynamic inventory via the rax module?

like image 363
jchamberlain Avatar asked Jul 22 '14 19:07

jchamberlain


2 Answers

You can manually edit the rax.py file and change line 125 and line 163 from:

hostvars['ansible_ssh_host'] = server.accessIPv4

to:

hostvars['ansible_ssh_host'] = server.addresses['private'][0]['addr']

This should make the value of ansible_ssh_host the private IP.

like image 60
bkan Avatar answered Sep 17 '22 18:09

bkan


My first thought on this is to treat it like you have a tunnel you need to set up.

When you use the rax module, it creates a group called "raxhosts". By default, these are accessed using that public ipv4 address.

You could create another group using that group (via add_host), but specify the IP you want to actually access it through.

- name: Redirect to raxprivhosts
  local_action:
      module: add_host
      hostname: "{{ item.name }}"
      ansible_ssh_host: "{{ item.rax_addresses['private'][0]['addr'] }}"
      ansible_ssh_pass: "{{ item.rax_adminpass }}"
      groupname: raxprivhosts
  with_items: raxhosts

Then apply playbooks against those groups as your follow on actions.

Let me know how this works out for you, I'm just throwing it out as an alternate to changing your rax.py manually.

like image 30
Kyle Kelley Avatar answered Sep 21 '22 18:09

Kyle Kelley