add_host after Rackspace Provisioning

I’m running into some trouble with Rackspace provisioning. I am attempting to provision a new host and then add it to the in-memory host to continue with the rest of the plays.

The provisioning looks like this:

  • name: “Ensure {{ num_tomcat_servers }} Tomcat servers exist”
    local_action:
    module: rax
    api_key:
    username:
    region:
    service: cloudservers
    state: active
    wait: yes
    wait_timeout: 600
    flavor:
    image:
    name: ‘identifier-tomcat-{{ item }}’
    meta:
    group: tomcat
    with_sequence: count={{ num_tomcat_servers }}
    register: tomcat_hosts
    notify:
  • Register tomcat instances
  • Group tomcat instances

Then, I have these handlers invoked:

handlers:

  • name: Register tomcat instances
    local_action: add_host name={{ item.accessIPv4 }} groups={{ item.name }}
    with_items: tomcat_hosts.instances

  • name: Group tomcat instances
    local_action: add_host name={{ item.accessIPv4 }} groups=tomcat
    with_items: tomcat_hosts.instances

The idea here is that I will add all of the instances to their respective name group (identifer-tomcat-1, identifier-tomcat-2, etc) as well as a more generic group called ‘tomcat’. This is the only way that I could figure out how to do that (using 2 handlers)

The issue that I get is in the handler. It seems to bomb out on the add_host line:

Can you re-run the playbook with the ‘-v’ flag?

That should provide you debug information about the items in the loop from with_items.

I ran with -vvvv but I only included the non-SSH output; let me know if I should post some of that. I also scrubbed the IP address from the provisioned server along with it’s ID but it all looked right.

Ah, I see the issue.

When you do a ‘register’ in combination with ‘with_sequence’, you get back a response that has a ‘results’ attribute that contains a list of each of the individual responses. You will need to loop through that. Something like:

handlers:

  • name: Register tomcat instances
    local_action: add_host name={{ item.instances[0].accessIPv4 }} groups={{ item.instances[0].name }}
    with_items: tomcat_hosts.results

Currently, the rax module, will only create a single host at a time, which is likely why you are using with_sequence. So referencing index 0 should be somewhat safe.

It is on my to do list to add “count” functionality to the rax module, so that this isn’t needed. I’ve been working on a number of new features for it already.

Hm ok I think I understand. So then the handler would be executed multiple times, once for each item in the sequence? That seems like the only scenario that referencing index 0 for the instances list would be safe, right?

Actually no, let me answer my own question here. The handler itself is only executed once which is fine: we’re actually looping through a list of ‘results’ which is what gets yielded from with_sequence. Each item in the results list has an ‘instances’ attribute which is a single-element list. Do I understand correctly?

Also, is there any other way I would know about this ‘results’ attribute on the response without you telling me or super deep diving into the source? I wouldn’t mind updating some docs for the next poor sap that comes along :). I guess the documentation item here would be to say what the priority of yields are (with_sequence happens after the rax creation command in this case).

Although to be honest, at this point this has turned into a bit of an academic discussion. Rackspace has recently been taking quite a while to provision servers (sometimes 10-15 minutes) so it has become impractical to expect instantiation and provisioning to occur all within the same playbook.

Thanks for your help! Lifesaver!

I believe you understand correctly.

As far as the ‘results’ attribute, I implemented a simple test case, and then used ‘debug’ to print out my registered variable. It doesn’t seem to be documented currently, but it looks like playbooks_loops.rst would be the likely place for it to show up.

The other current ‘issue’ with the ‘rax’ module, is that it acts in a serial manner. Because you call it once per loop, the ‘wait’ parameter causes ansible to kick off a build and wait for it to become active before moving on to the next server. Generally a linux server may take less than 5 minutes to build, so as you add more, it would be 5*n minutes.

I’m working on this as well, but don’t yet have anything to show for it yet. I hope to have something soonish…