Issue adding multiple Windows servers to same vSphere DRS group

The playbook log shows each server as being added to the DRS group, but only the last server processed is actually there

  • ansible [core 2.13.13]
  • Rocky Linux 8.10

The playbook looks like this:

- name: add VMs to an existing DRS group
  community.vmware.vmware_drs_group_manager:
    hostname: "{{ vsphere_host.data.Value }}"
    username: "{{ vsphere_username }}"
    password: "{{ vsphere_password }}"
    cluster: "{{ vsphere_cluster.data.Value }}"
    validate_certs: no
    datacenter: "{{ datacenter.data.Value }}"
    group_name: "{{ drs_group.data.Value }}"
    vms: 
      - "{{ inventory_hostname }}"
    state: present
  delegate_to: localhost

It retrieves some necessary values from Consul (vsphere_host, vsphere_cluster, datacenter, etc). It uses inventory_hostname to add the servers sequentially, which I guess is the problem.

In the output below, you can see SERVER01, SERVER02 and SERVER03, which are the 3 servers in my inventory. They were processed in the order 03, 01, 02 and SERVER02 is the only one in the DRS Group when the job finishes. The others existed momentarily but were replaced by subsequent servers.

changed: [SERVER3 -> localhost] => changed=true 
  drs_group_member_info:
    ATL-Prod:
    - group_name: ATL-WindowsVMs
      type: vm
      vms:
      - SERVER03
  msg: Updated vm group ATL-WindowsVMs successfully
changed: [SERVER01 -> localhost] => changed=true 
  drs_group_member_info:
    ATL-Prod:
    - group_name: ATL-WindowsVMs
      type: vm
      vms:
      - SERVER01
  msg: Updated vm group ATL-WindowsVMs successfully
changed: [SERVER02 -> localhost] => changed=true 
  drs_group_member_info:
    ATL-Prod:
    - group_name: ATL-WindowsVMs
      type: vm
      vms:
      - SERVER02
  msg: Updated vm group ATL-WindowsVMs successfully

I don’t understand this behavior. Modifying the job and adding the servers explicitly works as expected:

- name: add VMs to an existing DRS group
  community.vmware.vmware_drs_group_manager:
    hostname: "{{ vsphere_host.data.Value }}"
    username: "{{ vsphere_username }}"
    password: "{{ vsphere_password }}"
    cluster: "{{ vsphere_cluster.data.Value }}"
    validate_certs: no
    datacenter: "{{ datacenter.data.Value }}"
    group_name: "{{ drs_group.data.Value }}"
    vms: 
      - "SERVER01"
      - "SERVER02"
      - "SERVER03"
    state: present
  delegate_to: localhost

But it’s not really helpful for automation to do it that way. Thanks for looking!

ps - guy on my team is having the same issue working with Linux servers so doesn’t appear to be OS related.

What version of community.vmware and vsphere/vmware/esxi are you using?

Does this DRS group already have vms in it? When you add to an existing group that already has vms in it, does this add the last vm to the group, or does the last vm become the only vm in the group?

  • If it’s the former, then there is probably a race issue where you’re adding new vm’s before the previous additions are fully-committed for some reason.

  • If it’s the latter, then there’s either a bug or the documentation is misleading/incorrect and you need to list all vms for the group when “adding” them.

In either case, you could use the “workaround” you found as the default approach. This should be faster anyways since you would save time by adding your vm’s to the DRS group in bulk instead of one at a time. Obviously, you would want to do this programmatically instead of as a static list.

The following adds all of the {{ inventory_hostname }}'s by group (if exists) or active in the play:

- name: add VMs to an existing DRS group
  community.vmware.vmware_drs_group_manager:
    hostname: "{{ vsphere_host.data.Value }}"
    username: "{{ vsphere_username }}"
    password: "{{ vsphere_password }}"
    cluster: "{{ vsphere_cluster.data.Value }}"
    validate_certs: no
    datacenter: "{{ datacenter.data.Value }}"
    group_name: "{{ drs_group.data.Value }}"
    vms: "{{ groups['servers'] | default(play_hosts) }}"
    state: present
  delegate_to: localhost
  run_once: true

If your DRS Group’s vms membership is a bit more nuanced/complex than in my example, it should still be possible to come up with a programmatic list with enough creativity.

1 Like

First off, thanks for the quick response. I will address your questions, then look at your suggestions and update further after I’ve had time to focus on them (meetings today).

community.vmware is latest (4.5.0), vSphere version 7.0.3.01900

The DRS group does contain existing servers. When dealing with multiple servers as described in my 1st scenario, it appears to add the first, then it removes that one and adds the 2nd, and so on and so on until it removes the 2nd to last and adds the last, which is the only one that remains.

After posting the question, I started doing what you mentioned, which is a workaround to supply all the servers in 1 go but the way you suggested looks much cleaner. I will test that out and get back this morning.

Again, thanks for your input!

I think what’s happening is that community.vmware.vmware_drs_group_manager queries vsphere for all of the existing vms in the group you want to add to, merges that list with what you’re adding in your task (which is only the current host), then posts that entire list back to vsphere.

Since by default, Ansible will be running 5 forks, and therefore up to 5 inventory hosts at a time in parallel, each host will query vsphere at roughly the same time and get the same initial list. Each host adds themself to that list, and posts it back to vsphere, but now each inventory host has posted a different list that’s excluding each other. So of course, the last server to post wins.

@mariolenz might be able to confirm my suspicion.


Aside from running the task once and posting a list of all the servers you want to add in bulk (which I still recommend), another workaround might be to set throttle: 1 to make sure only one host is updating vsphere at a time. This might give enough time for vsphere to include the newly added vm in subsequent queries.

e.g.

- name: add VMs to an existing DRS group
  community.vmware.vmware_drs_group_manager:
    hostname: "{{ vsphere_host.data.Value }}"
    username: "{{ vsphere_username }}"
    password: "{{ vsphere_password }}"
    cluster: "{{ vsphere_cluster.data.Value }}"
    validate_certs: no
    datacenter: "{{ datacenter.data.Value }}"
    group_name: "{{ drs_group.data.Value }}"
    vms:
      - "{{ inventory_hostname }}"
    state: present
  delegate_to: localhost
  throttle: 1

That makes a lot of sense. I’m really close to being able to test out your 1st suggestion, for which I have high hopes. I will update with the results soon and thank you!

1 Like

I can confirm that this was the solution:

- name: add VMs to an existing DRS group
  community.vmware.vmware_drs_group_manager:
    hostname: "{{ vsphere_host.data.Value }}"
    username: "{{ vsphere_username }}"
    password: "{{ vsphere_password }}"
    cluster: "{{ vsphere_cluster.data.Value }}"
    validate_certs: no
    datacenter: "{{ datacenter.data.Value }}"
    group_name: "{{ drs_group.data.Value }}"
    vms: "{{ groups['servers'] | default(play_hosts) }}"
    state: present
  delegate_to: localhost
  run_once: true

Many thanks to you, @Denney-tech !!

1 Like

I’ve posted 2 questions in here and you’ve ( @Denney-tech ) answered them both. Such service.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.