Repository: ansible-collections/community.vmware

Issue:
Configure resource shares on a per vm basis in vmware_guest
##### SUMMARY
Be able to specify resource shares on a per vm basis in the vmware_guest module. Currently one can only specify limits and/or reservations.

##### ISSUE TYPE
Add new choices to hardware parameter in vmware_guest module.

`cpu_shares` (string): low, normal, high, custom (DEFAULT: normal)
`memory_shares` (string): low, normal, high, custom, (DEFAULT: normal)

##### COMPONENT NAME
vmware_guest

##### ADDITIONAL INFORMATION
Sometime, especially if you do not make use of resource pools in genereal, you have the need to modify shares settings on a per vm basis.



Discussion:
Files identified in the description:
* [`plugins/modules/vmware_guest.py`](https://github.com/ansible-collections/vmware/blob/main/plugins/modules/vmware_guest.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
@johnnnnnnnnnnnnnn: Greetings! Thanks for taking the time to open this issue. In order for the community to handle your issue effectively, we need a bit more information.

Here are the items we could not find in your description:
- ansible version

Please set the description of this issue with this template:
https://raw.githubusercontent.com/ansible/ansible/devel/.github/ISSUE_TEMPLATE/bug_report.md

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: issue_missing_data --->
cc @Akasurde @Tomorrow9 @goneri @lparkes @nerzhul @pdellaert @pgbidkar @warthog9
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/plugins/modules/vmware_guest.py b/plugins/modules/vmware_guest.py
--- a/plugins/modules/vmware_guest.py
+++ b/plugins/modules/vmware_guest.py
@@ -149,6 +149,19 @@
         num_cpu_cores_per_socket:
             type: int
             description: Number of Cores Per Socket.
+        cpu_shares_level:
+            type: str
+            choices: [ 'low', 'normal', 'high', 'custom' ]
+            description:
+            - The allocation level of CPU resources for the virtual machine.
+            - Valid Values are C(low), C(normal), C(high) and C(custom).
+            version_added: '3.2.0'
+        cpu_shares:
+            type: int
+            description:
+            - The number of shares of CPU allocated to this virtual machine
+            - cpu_shares_level will automatically be set to 'custom'
+            version_added: '3.2.0'
         scsi:
             type: str
             description:
@@ -175,6 +188,19 @@
             type: int
             description: The amount of memory resource that is guaranteed available to the virtual machine.
             aliases: [ 'memory_reservation' ]
+        mem_shares_level:
+            type: str
+            description:
+            - The allocation level of memory resources for the virtual machine.
+            - Valid Values are C(low), C(normal), C(high) and C(custom).
+            choices: [ 'low', 'normal', 'high', 'custom' ]
+            version_added: '3.2.0'
+        mem_shares:
+            type: int
+            description:
+            - The number of shares of memory allocated to this virtual machine
+            - mem_shares_level will automatically be set to 'custom'
+            version_added: '3.2.0'
         cpu_limit:
             type: int
             description:
@@ -809,6 +835,8 @@
       memory_reservation_lock: True
       mem_limit: 8096
       mem_reservation: 4096
+      cpu_shares_level: "high"
+      mem_shares_level: "high"
       cpu_limit: 8096
       cpu_reservation: 4096
       max_connections: 5
@@ -1215,6 +1243,44 @@ def configure_resource_alloc_info(self, vm_obj):
         memory_allocation = vim.ResourceAllocationInfo()
         cpu_allocation = vim.ResourceAllocationInfo()
 
+        memory_shares_info = vim.SharesInfo()
+        cpu_shares_info = vim.SharesInfo()
+
+        mem_shares_level = self.params['hardware']['mem_shares_level']
+        if mem_shares_level is not None:
+            memory_shares_info.level = mem_shares_level
+            memory_allocation.shares = memory_shares_info
+
+            if vm_obj is None or \
+                    memory_allocation.shares.level != vm_obj.config.memoryAllocation.shares.level:
+                rai_change_detected = True
+
+        cpu_shares_level = self.params['hardware']['cpu_shares_level']
+        if cpu_shares_level is not None:
+            cpu_shares_info.level = cpu_shares_level
+            cpu_allocation.shares = cpu_shares_info
+            if vm_obj is None or \
+                    cpu_allocation.shares.level != vm_obj.config.cpuAllocation.shares.level:
+                rai_change_detected = True
+
+        mem_shares = self.params['hardware']['mem_shares']
+        if mem_shares is not None:
+            memory_shares_info.level = 'custom'
+            memory_shares_info.shares = mem_shares
+            memory_allocation.shares = memory_shares_info
+            if vm_obj is None or \
+                    memory_allocation.shares != vm_obj.config.memoryAllocation.shares:
+                rai_change_detected = True
+
+        cpu_shares = self.params['hardware']['cpu_shares']
+        if cpu_shares is not None:
+            cpu_shares_info.level = 'custom'
+            cpu_shares_info.shares = cpu_shares
+            cpu_allocation.shares = cpu_shares_info
+            if vm_obj is None or \
+                    cpu_allocation.shares != vm_obj.config.cpuAllocation.shares:
+                rai_change_detected = True
+
         mem_limit = self.params['hardware']['mem_limit']
         if mem_limit is not None:
             memory_allocation.limit = mem_limit
@@ -3317,6 +3383,10 @@ def main():
                 hotremove_cpu=dict(type='bool'),
                 max_connections=dict(type='int'),
                 mem_limit=dict(type='int'),
+                cpu_shares_level=dict(type='str', choices=['low', 'normal', 'high', 'custom']),
+                mem_shares_level=dict(type='str', choices=['low', 'normal', 'high', 'custom']),
+                cpu_shares=dict(type='int'),
+                mem_shares=dict(type='int'),
                 mem_reservation=dict(type='int', aliases=['memory_reservation']),
                 memory_mb=dict(type='int'),
                 memory_reservation_lock=dict(type='bool'),


Test patch:
diff --git a/tests/integration/targets/vmware_guest/defaults/main.yml b/tests/integration/targets/vmware_guest/defaults/main.yml
--- a/tests/integration/targets/vmware_guest/defaults/main.yml
+++ b/tests/integration/targets/vmware_guest/defaults/main.yml
@@ -18,6 +18,7 @@ vmware_guest_test_playbooks:
   - mac_address_d1_c1_f0.yml
   - max_connections.yml
   - mem_reservation.yml
+  - shares.yml
   - multiple_disk_controllers_d1_c1_f0.yml
   - network_negative_test.yml
   - network_with_device.yml
diff --git a/tests/integration/targets/vmware_guest/tasks/shares.yml b/tests/integration/targets/vmware_guest/tasks/shares.yml
new file mode 100644
--- /dev/null
+++ b/tests/integration/targets/vmware_guest/tasks/shares.yml
@@ -0,0 +1,122 @@
+# Test code for the vmware_guest module.
+# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.com>
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- &add_cpu_shares
+  name: Create new VMs with cpu shares level set to High
+  vmware_guest:
+    validate_certs: false
+    hostname: "{{ vcenter_hostname }}"
+    username: "{{ vcenter_username }}"
+    password: "{{ vcenter_password }}"
+    name: test_vm1
+    guest_id: centos64Guest
+    datacenter: "{{ dc1 }}"
+    hardware:
+      num_cpus: 1
+      memory_mb: 128
+      cpu_shares_level: high
+    disk:
+      - size: 1gb
+        type: thin
+        datastore: "{{ rw_datastore }}"
+    state: present
+    folder: "{{ virtual_machines[0].folder }}"
+  register: cpu_shares_level_result_0001
+
+- debug: var=cpu_shares_level_result_0001
+
+- name: Assert that changes were made
+  assert:
+    that:
+      - cpu_shares_level_result_0001 is changed
+
+- <<: *add_cpu_shares
+  name: Again create new VMs with CPU shares level set to High
+  register: cpu_shares_level_result_0002
+
+- debug: var=cpu_shares_level_result_0002
+
+- name: Assert that changes were not made
+  assert:
+    that:
+      - not (cpu_shares_level_result_0002 is changed)
+
+- &add_mem_shares
+  name: Create new VM with memory shares level set to High
+  vmware_guest:
+    validate_certs: false
+    hostname: "{{ vcenter_hostname }}"
+    username: "{{ vcenter_username }}"
+    password: "{{ vcenter_password }}"
+    name: test_vm2
+    guest_id: centos64Guest
+    datacenter: "{{ dc1 }}"
+    hardware:
+      num_cpus: 1
+      memory_mb: 128
+      mem_shares_level: high
+    disk:
+      - size: 1gb
+        type: thin
+        datastore: "{{ rw_datastore }}"
+    state: present
+    folder: "{{ virtual_machines[0].folder }}"
+  register: mem_shares_level_results_0003
+
+- debug: var=mem_shares_level_results_0003
+
+- name: Assert that changes were made
+  assert:
+    that:
+      - mem_shares_level_results_0003 is changed
+
+- <<: *add_mem_shares
+  name: Again create new VMs with memory shares level set to High
+  register: mem_shares_level_results_0004
+
+- debug: var=mem_shares_level_results_0004
+
+- name: Assert that changes were not made
+  assert:
+    that:
+      - not (mem_shares_level_results_0004 is changed)
+
+- &no_shares_levels
+  name: Create new VMs without CPU or Memory Shares level set
+  vmware_guest:
+    validate_certs: false
+    hostname: "{{ vcenter_hostname }}"
+    username: "{{ vcenter_username }}"
+    password: "{{ vcenter_password }}"
+    name: test_vm3
+    guest_id: centos64Guest
+    datacenter: "{{ dc1 }}"
+    hardware:
+      num_cpus: 1
+      memory_mb: 128
+    disk:
+      - size: 1gb
+        type: thin
+        datastore: "{{ rw_datastore }}"
+    state: present
+    folder: "{{ virtual_machines[0].folder }}"
+  register: no_shares_levels_results_0005
+
+- debug: var=no_shares_levels_results_0005
+
+- name: Assert that changes were made
+  assert:
+    that:
+      - no_shares_levels_results_0005 is changed
+
+- <<: *no_shares_levels
+  name: Again create new VMs without memory_reservation or mem_reservation
+  register: no_shares_levels_result_0006
+
+- debug: var=no_shares_levels_result_0006
+
+- name: Assert that changes were not made
+  assert:
+    that:
+      - not (no_shares_levels_result_0006 is changed)