add_host after Rackspace Provisioning

571 views
Skip to first unread message

Phillip Verheyden

unread,
Oct 8, 2013, 12:39:44 PM10/8/13
to ansible...@googlegroups.com
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: <excluded>
        username:  <excluded>
        region:  <excluded>
        service: cloudservers
        state: active
        wait: yes
        wait_timeout: 600
        flavor:  <excluded>
        image:  <excluded>
        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:

 _____________________________________ 
< NOTIFIED: Register tomcat instances >
 ------------------------------------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||


fatal: [127.0.0.1] => One or more undefined variables: 'str object' has no attribute 'accessIPv4'

I can't seem to figure out what I'm doing wrong. The Rackspace plugin returns the following after it succeeds: 

    module.exit_json(changed=changed, instances=instances)

Where each item in 'instances' is this:

instance = {'id': server.id,
                            'accessIPv4': server.accessIPv4,
                            'name': server.name,
                            'status': server.status}

Anybody have any juice on this? It almost seems like the {{ item }} reference in the handler is attempting to use the {{ item }} from the sequence above. I'll keep debugging to see if I can obtain any additional information.

-- 
Phillip Verheyden

Matt Martz

unread,
Oct 8, 2013, 1:28:53 PM10/8/13
to ansible...@googlegroups.com
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.

-- 
Matt Martz

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Phillip Verheyden

unread,
Oct 8, 2013, 3:36:27 PM10/8/13
to ansible...@googlegroups.com
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.

__________________ 
< PLAY [localhost] >
 ------------------ 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||


 _________________ 
< GATHERING FACTS >
 ----------------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||


ok: [127.0.0.1]
 _____________________________________ 
< TASK: Ensure 1 Tomcat servers exist >
 ------------------------------------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||



changed: [127.0.0.1] => (item=1) => {"changed": true, "instances": [{"accessIPv4": "<some IP address>", "id": "4234201345814-3240-23-4-14--32", "name": "identifier-tomcat-1", "status": "ACTIVE"}], "item": "1"}
 _____________________________________ 
< NOTIFIED: Register tomcat instances >
 ------------------------------------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||


fatal: [127.0.0.1] => One or more undefined variables: 'str object' has no attribute 'accessIPv4'
 __________________________________ 
< NOTIFIED: Group tomcat instances >
 ---------------------------------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||


FATAL: no hosts matched or all hosts have already failed -- aborting

 ________________________ 
< PLAY [identifier-tomcat*] >
 ------------------------ 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||


skipping: no hosts matched
 ____________ 
< PLAY RECAP >
 ------------ 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||


           to retry, use: --limit @/path/to/playbook.retry

127.0.0.1                  : ok=2    changed=1    unreachable=0    failed=1   

-- 
Phillip Verheyden

Matt Martz

unread,
Oct 8, 2013, 4:00:26 PM10/8/13
to ansible...@googlegroups.com
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.

-- 
Matt Martz

Phillip Verheyden

unread,
Oct 8, 2013, 4:15:21 PM10/8/13
to ansible...@googlegroups.com
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!

-- 
Phillip Verheyden

Matt Martz

unread,
Oct 8, 2013, 4:27:16 PM10/8/13
to ansible...@googlegroups.com
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...

-- 
Matt Martz

Reply all
Reply to author
Forward
0 new messages