Is there any way to re-use authentications or otherwise do efficient loops in the community.vmware module?

Hello,

We are using Ansible in order to manipulate VM tags in vCenter, using the VMware Tag Manager module. It works ok, but it seems to authenticate against the vcenter anew with every invocation. For large tagging operations (hundreds of VMs), it is a not-insubstantial factor in runtime.

A stripped-down example of the code used:

-  name: Tag All VMs
   loop: "{{ inventory }}"
   vmware_tag_manager:
     hostname: "{{ hostvars[item]['dest']['vcenter_IP'] }}"
     username: "{{ hostvars[item]['dest']['username'] }}"
     password: "{{ hostvars[item]['dest']['password'] }}"
     tag_names: "{{ tag_names }}"
     object_name: "{{ object_name }}"
     object_type: VirtualMachine
     state: add
     .....

One factor is that we are dynamically resolving the particular vCenter a VM belongs to at module runtime.

Is there any way that this authentication to the vcenter can be re-used? Alternatively, is there a more efficient way to use this module to tag many VMs using just one or a few invocations?

Edit: Ah, I think I misunderstood the question. It sounded like you wanted to get rid of boilerplate throughout your play (which is what module_defaults helps with), but my suggestion won’t help reduce the number of authentications made.

You can set module_defaults at the play or block level for individual modules, or the group the collection defines in its meta/runtime.yml (community.vmware/meta/runtime.yml at main · ansible-collections/community.vmware · GitHub) to configure all modules in the group.

- hosts: all
  gather_facts: no
  module_defaults:
    community.vmware.vmware_tag_manager:
      # defaults for specific module
       ...
    group/community.vmware.vmware:
      # defaults for all modules/action plugins in the group
      hostname: '{{ vcenter_hostname }}'
      username: '{{ vcenter_username }}'
      password: '{{ vcenter_password }}'
      port: "{{ vcenter_port|default('443') }}"
      validate_certs: "{{ vmware_validate_certs|default('no') }}"
  tasks:
    - vmware_tag_manager:
        tag_names: "{{ tag_names }}"
        object_name: "{{ object_name }}"
        object_type: VirtualMachine
        state: add

This is also a collection that has a legacy group name (ansible/lib/ansible/config/ansible_builtin_runtime.yml at devel · ansible/ansible · GitHub), so you can use group/vmware: instead of typing the fully qualified group name.

I agree, this really sucks. I didn’t find a way to re-use sessions in this collection, though.

That is, to implement this in the collection itself. For you as a user of the collection there’s no way to do it.

I have seen some modules that have the ability to use cached credentials/tokens so they don’t have to reauthenticate with each invocation. Too bad I can’t remember where I saw that, maybe some networking related modules. The idea is to use one module for authentication and caching of auth tokens and subsequent modules use that cache to auth. VMware modules, including the new modules using the REST API, unfortunately seem to not have that ability.

On the other hand, are you sure reauth is what takes a significant percentage of module execution time? Module invocation itself is a rather heavy operation in Ansible. Module execution is usually quick but waiting for API call to vCenter to finish is much slower. I think that authentication takes small percentage of that time.

Also, unless vCenter API offers the ability to tag multiple objects with a single call, this is the only way it can be implemented. API call has to be made for each single object that is to be tagged.

For the record: test turbo server

2 Likes

Someone I’ve talked about this said:

there have been a number of partially-failed attempts in this area that have actually shipped as part of core over the years- most have been removed (accelerate, turbo). It’s not hard at all to get a persistent reusable module state process to hang around- the hard part is getting it to play nicely/safely. Common problems with previous attempts:

  • process lifetime management (control-node-only is much easier, hard-tied to control process lifetime, preventing process clog, multiple overlapping jobs, different concurrent versions of core/content)
  • robust pool key selection (eg, host/port/credential/?- making sure you don’t pick up the wrong one)
  • secure access to the cached process (esp where become is a factor)

Sounds like this is hard to implement in a safe / secure / (maybe?) stable way. Especially since each task is a separate process. I think this makes it complicated. We can’t use shared memory between threads, we need inter-process communication.

1 Like