We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Feature: vmware_guest_tools_upgrade to be applied without forcing reboot
<!--- Verify first that your feature was not already discussed on GitHub -->
<!--- Complete *all* sections as described, this form is processed automatically -->

##### SUMMARY
<!--- Describe the new feature/improvement briefly below -->
vmware_guest_tools_upgrade should support shutdown as an option

##### ISSUE TYPE
- Feature Idea
- Users may wish to apply the latest vmtools without rebooting immediately.

##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below, use your best guess if unsure -->
- https://github.com/ansible-collections/community.vmware/blob/main/plugins/module_utils/vmware.py#L968

##### ADDITIONAL INFORMATION
<!--- Describe how the feature would be used, why it is needed and what it would solve -->
- This allows the flexibility to set the desired state and then schedule the reboot in a production environment.
<!--- Paste example playbooks or commands between quotes below -->
```yaml
---
- name: Upgrade VMtools
  hosts: "{{ ansible_hosts }}"
  gather_facts: false
  become: true
  tasks:

    - name: Upgrade VMtools
      community.vmware.vmware_guest_tools_upgrade:
        hostname: "{{ vcenter_url }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        datacenter: "{{ datacenter_name }}"
        name: "{{ inventory_hostname.split('_')[0] }}"
        validate_certs: "{{ vcenter_cert_validation }}"
        allow_reboot: false
      become: false
      delegate_to: localhost
```

<!--- HINT: You can also paste gist.github.com links for larger files -->


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `plugins/modules/vmware_guest_tools_upgrade.py`
Content:
```
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 
4 # Copyright: (c) 2018, Mike Klebolt  <michael.klebolt@centurylink.com>
5 # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
6 # SPDX-License-Identifier: GPL-3.0-or-later
7 
8 from __future__ import (absolute_import, division, print_function)
9 __metaclass__ = type
10 
11 
12 DOCUMENTATION = r'''
13 ---
14 module: vmware_guest_tools_upgrade
15 short_description: Module to upgrade VMTools
16 description:
17     - This module upgrades the VMware Tools on Windows and Linux guests and reboots them.
18 notes:
19     - "In order to upgrade VMTools, please power on virtual machine before hand - either 'manually' or
20       using module M(community.vmware.vmware_guest_powerstate)."
21 options:
22    name:
23         description:
24             - Name of the virtual machine to work with.
25             - 'This is required if O(uuid) or O(moid) is not supplied.'
26         type: str
27    name_match:
28         description:
29             - If multiple virtual machines matching the name, use the first or last found.
30         default: 'first'
31         choices: ['first', 'last']
32         type: str
33    uuid:
34         description:
35             - "UUID of the instance to manage if known, this is VMware's unique identifier."
36             - This is required if O(name) or O(moid) is not supplied.
37         type: str
38    moid:
39         description:
40             - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance.
41             - This is required if O(name) or O(uuid) is not supplied.
42         type: str
43    folder:
44         description:
45             - Destination folder, absolute or relative path to find an existing guest.
46             - This is required, if O(name) is supplied.
47             - "The folder should include the datacenter. ESX's datacenter is ha-datacenter"
48             - 'Examples:'
49             - '   folder: /ha-datacenter/vm'
50             - '   folder: ha-datacenter/vm'
51             - '   folder: /datacenter1/vm'
52             - '   folder: datacenter1/vm'
53             - '   folder: /datacenter1/vm/folder1'
54             - '   folder: datacenter1/vm/folder1'
55             - '   folder: /folder1/datacenter1/vm'
56             - '   folder: folder1/datacenter1/vm'
57             - '   folder: /folder1/datacenter1/vm/folder2'
58         type: str
59    datacenter:
60         description:
61             - Destination datacenter where the virtual machine exists.
62         required: true
63         type: str
64    force_upgrade:
65         description:
66             - This flag overrides the guest operating system detection and forcibly upgrade VMware tools or open-vm-tools.
67             - "This is useful when VMware tools is too old and unable to detect the 'guestFamily' value."
68             - 'Using this flag may sometime give unexpected results since module will override the default'
69             - "behaviour of 'guestFamily' detection."
70         default: false
71         type: bool
72         required: false
73 extends_documentation_fragment:
74 - community.vmware.vmware.documentation
75 
76 author:
77     - Mike Klebolt (@MikeKlebolt) <michael.klebolt@centurylink.com>
78 '''
79 
80 EXAMPLES = r'''
81 - name: Get VM UUID
82   vmware_guest_facts:
83     hostname: "{{ vcenter_hostname }}"
84     username: "{{ vcenter_username }}"
85     password: "{{ vcenter_password }}"
86     datacenter: "{{ datacenter }}"
87     folder: "/{{datacenter}}/vm"
88     name: "{{ vm_name }}"
89   delegate_to: localhost
90   register: vm_facts
91 
92 - name: Upgrade VMware Tools using uuid
93   community.vmware.vmware_guest_tools_upgrade:
94     hostname: "{{ vcenter_hostname }}"
95     username: "{{ vcenter_username }}"
96     password: "{{ vcenter_password }}"
97     datacenter: "{{ datacenter_name }}"
98     uuid: "{{ vm_facts.instance.hw_product_uuid }}"
99   delegate_to: localhost
100 
101 - name: Upgrade VMware Tools using MoID
102   community.vmware.vmware_guest_tools_upgrade:
103     hostname: "{{ vcenter_hostname }}"
104     username: "{{ vcenter_username }}"
105     password: "{{ vcenter_password }}"
106     datacenter: "{{ datacenter_name }}"
107     moid: vm-42
108   delegate_to: localhost
109 '''
110 
111 RETURN = r''' # '''
112 
113 
114 from ansible.module_utils.basic import AnsibleModule
115 from ansible_collections.community.vmware.plugins.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task
116 from ansible.module_utils._text import to_native
117 
118 
119 class PyVmomiHelper(PyVmomi):
120     def __init__(self, module):
121         super(PyVmomiHelper, self).__init__(module)
122 
123     def upgrade_tools(self, vm):
124         result = {'failed': False, 'changed': False, 'msg': ''}
125         # Exit if VMware tools is already up to date
126         if vm.guest.toolsStatus == "toolsOk":
127             result.update(
128                 changed=False,
129                 msg="VMware tools is already up to date",
130             )
131             return result
132 
133         # Fail if VM is not powered on
134         elif vm.summary.runtime.powerState != "poweredOn":
135             result.update(
136                 failed=True,
137                 msg="VM must be powered on to upgrade tools",
138             )
139             return result
140 
141         # Fail if VMware tools is either not running or not installed
142         elif vm.guest.toolsStatus in ["toolsNotRunning", "toolsNotInstalled"]:
143             result.update(
144                 failed=True,
145                 msg="VMware tools is either not running or not installed",
146             )
147             return result
148 
149         # If vmware tools is out of date, check major OS family
150         # Upgrade tools on Linux and Windows guests
151         elif vm.guest.toolsStatus == "toolsOld":
152             try:
153                 force = self.module.params.get('force_upgrade')
154                 if force or vm.guest.guestFamily in ["linuxGuest", "windowsGuest"]:
155                     task = vm.UpgradeTools()
156                     changed, err_msg = wait_for_task(task)
157                     result.update(changed=changed, msg=to_native(err_msg))
158                 else:
159                     result.update(msg='Guest Operating System is other than Linux and Windows.')
160                 return result
161             except Exception as exc:
162                 result.update(
163                     failed=True,
164                     msg='Error while upgrading VMware tools %s' % to_native(exc),
165                 )
166                 return result
167         else:
168             result.update(
169                 failed=True,
170                 msg="VMware tools could not be upgraded",
171             )
172             return result
173 
174 
175 def main():
176     argument_spec = vmware_argument_spec()
177     argument_spec.update(
178         name=dict(type='str'),
179         name_match=dict(type='str', choices=['first', 'last'], default='first'),
180         uuid=dict(type='str'),
181         moid=dict(type='str'),
182         folder=dict(type='str'),
183         datacenter=dict(type='str', required=True),
184         force_upgrade=dict(type='bool', default=False),
185     )
186     module = AnsibleModule(
187         argument_spec=argument_spec,
188         required_one_of=[
189             ['name', 'uuid', 'moid']
190         ]
191     )
192 
193     if module.params['folder']:
194         # FindByInventoryPath() does not require an absolute path
195         # so we should leave the input folder path unmodified
196         module.params['folder'] = module.params['folder'].rstrip('/')
197 
198     pyv = PyVmomiHelper(module)
199     # Check if the VM exists before continuing
200     vm = pyv.get_vm()
201 
202     # VM already exists
203     if vm:
204         try:
205             result = pyv.upgrade_tools(vm)
206             if result['changed']:
207                 module.exit_json(changed=result['changed'])
208             elif result['failed']:
209                 module.fail_json(msg=result['msg'])
210             else:
211                 module.exit_json(msg=result['msg'], changed=result['changed'])
212         except Exception as exc:
213             module.fail_json(msg='Unknown error: %s' % to_native(exc))
214     else:
215         vm_id = module.params.get('uuid') or module.params.get('name') or module.params.get('moid')
216         module.fail_json(msg='Unable to find VM %s' % vm_id)
217 
218 
219 if __name__ == '__main__':
220     main()
221
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/plugins/modules/vmware_guest_tools_upgrade.py b/plugins/modules/vmware_guest_tools_upgrade.py
--- a/plugins/modules/vmware_guest_tools_upgrade.py
+++ b/plugins/modules/vmware_guest_tools_upgrade.py
@@ -70,6 +70,12 @@
         default: false
         type: bool
         required: false
+   installer_options:
+        version_added: '4.1.0'
+        description:
+            - Command line options passed to the installer to modify the installation procedure for tools.
+        type: str
+        required: false
 extends_documentation_fragment:
 - community.vmware.vmware.documentation
 
@@ -151,8 +157,12 @@
         elif vm.guest.toolsStatus == "toolsOld":
             try:
                 force = self.module.params.get('force_upgrade')
+                installer_options = self.module.params.get('installer_options')
                 if force or vm.guest.guestFamily in ["linuxGuest", "windowsGuest"]:
-                    task = vm.UpgradeTools()
+                    if installer_options is not None:
+                        task = vm.UpgradeTools(installer_options)
+                    else:
+                        task = vm.UpgradeTools()
                     changed, err_msg = wait_for_task(task)
                     result.update(changed=changed, msg=to_native(err_msg))
                 else:
@@ -182,6 +192,7 @@
         folder=dict(type='str'),
         datacenter=dict(type='str', required=True),
         force_upgrade=dict(type='bool', default=False),
+        installer_options=dict(type='str'),
     )
     module = AnsibleModule(
         argument_spec=argument_spec,

{"golden_diff": "diff --git a/plugins/modules/vmware_guest_tools_upgrade.py b/plugins/modules/vmware_guest_tools_upgrade.py\n--- a/plugins/modules/vmware_guest_tools_upgrade.py\n+++ b/plugins/modules/vmware_guest_tools_upgrade.py\n@@ -70,6 +70,12 @@\n         default: false\n         type: bool\n         required: false\n+   installer_options:\n+        version_added: '4.1.0'\n+        description:\n+            - Command line options passed to the installer to modify the installation procedure for tools.\n+        type: str\n+        required: false\n extends_documentation_fragment:\n - community.vmware.vmware.documentation\n \n@@ -151,8 +157,12 @@\n         elif vm.guest.toolsStatus == \"toolsOld\":\n             try:\n                 force = self.module.params.get('force_upgrade')\n+                installer_options = self.module.params.get('installer_options')\n                 if force or vm.guest.guestFamily in [\"linuxGuest\", \"windowsGuest\"]:\n-                    task = vm.UpgradeTools()\n+                    if installer_options is not None:\n+                        task = vm.UpgradeTools(installer_options)\n+                    else:\n+                        task = vm.UpgradeTools()\n                     changed, err_msg = wait_for_task(task)\n                     result.update(changed=changed, msg=to_native(err_msg))\n                 else:\n@@ -182,6 +192,7 @@\n         folder=dict(type='str'),\n         datacenter=dict(type='str', required=True),\n         force_upgrade=dict(type='bool', default=False),\n+        installer_options=dict(type='str'),\n     )\n     module = AnsibleModule(\n         argument_spec=argument_spec,\n", "issue": "Feature: vmware_guest_tools_upgrade to be applied without forcing reboot\n<!--- Verify first that your feature was not already discussed on GitHub -->\r\n<!--- Complete *all* sections as described, this form is processed automatically -->\r\n\r\n##### SUMMARY\r\n<!--- Describe the new feature/improvement briefly below -->\r\nvmware_guest_tools_upgrade should support shutdown as an option\r\n\r\n##### ISSUE TYPE\r\n- Feature Idea\r\n- Users may wish to apply the latest vmtools without rebooting immediately.\r\n\r\n##### COMPONENT NAME\r\n<!--- Write the short name of the module, plugin, task or feature below, use your best guess if unsure -->\r\n- https://github.com/ansible-collections/community.vmware/blob/main/plugins/module_utils/vmware.py#L968\r\n\r\n##### ADDITIONAL INFORMATION\r\n<!--- Describe how the feature would be used, why it is needed and what it would solve -->\r\n- This allows the flexibility to set the desired state and then schedule the reboot in a production environment.\r\n<!--- Paste example playbooks or commands between quotes below -->\r\n```yaml\r\n---\r\n- name: Upgrade VMtools\r\n  hosts: \"{{ ansible_hosts }}\"\r\n  gather_facts: false\r\n  become: true\r\n  tasks:\r\n\r\n    - name: Upgrade VMtools\r\n      community.vmware.vmware_guest_tools_upgrade:\r\n        hostname: \"{{ vcenter_url }}\"\r\n        username: \"{{ vcenter_username }}\"\r\n        password: \"{{ vcenter_password }}\"\r\n        datacenter: \"{{ datacenter_name }}\"\r\n        name: \"{{ inventory_hostname.split('_')[0] }}\"\r\n        validate_certs: \"{{ vcenter_cert_validation }}\"\r\n        allow_reboot: false\r\n      become: false\r\n      delegate_to: localhost\r\n```\r\n\r\n<!--- HINT: You can also paste gist.github.com links for larger files -->\r\n\n", "before_files": [{"content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n\n# Copyright: (c) 2018, Mike Klebolt  <michael.klebolt@centurylink.com>\n# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)\n# SPDX-License-Identifier: GPL-3.0-or-later\n\nfrom __future__ import (absolute_import, division, print_function)\n__metaclass__ = type\n\n\nDOCUMENTATION = r'''\n---\nmodule: vmware_guest_tools_upgrade\nshort_description: Module to upgrade VMTools\ndescription:\n    - This module upgrades the VMware Tools on Windows and Linux guests and reboots them.\nnotes:\n    - \"In order to upgrade VMTools, please power on virtual machine before hand - either 'manually' or\n      using module M(community.vmware.vmware_guest_powerstate).\"\noptions:\n   name:\n        description:\n            - Name of the virtual machine to work with.\n            - 'This is required if O(uuid) or O(moid) is not supplied.'\n        type: str\n   name_match:\n        description:\n            - If multiple virtual machines matching the name, use the first or last found.\n        default: 'first'\n        choices: ['first', 'last']\n        type: str\n   uuid:\n        description:\n            - \"UUID of the instance to manage if known, this is VMware's unique identifier.\"\n            - This is required if O(name) or O(moid) is not supplied.\n        type: str\n   moid:\n        description:\n            - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance.\n            - This is required if O(name) or O(uuid) is not supplied.\n        type: str\n   folder:\n        description:\n            - Destination folder, absolute or relative path to find an existing guest.\n            - This is required, if O(name) is supplied.\n            - \"The folder should include the datacenter. ESX's datacenter is ha-datacenter\"\n            - 'Examples:'\n            - '   folder: /ha-datacenter/vm'\n            - '   folder: ha-datacenter/vm'\n            - '   folder: /datacenter1/vm'\n            - '   folder: datacenter1/vm'\n            - '   folder: /datacenter1/vm/folder1'\n            - '   folder: datacenter1/vm/folder1'\n            - '   folder: /folder1/datacenter1/vm'\n            - '   folder: folder1/datacenter1/vm'\n            - '   folder: /folder1/datacenter1/vm/folder2'\n        type: str\n   datacenter:\n        description:\n            - Destination datacenter where the virtual machine exists.\n        required: true\n        type: str\n   force_upgrade:\n        description:\n            - This flag overrides the guest operating system detection and forcibly upgrade VMware tools or open-vm-tools.\n            - \"This is useful when VMware tools is too old and unable to detect the 'guestFamily' value.\"\n            - 'Using this flag may sometime give unexpected results since module will override the default'\n            - \"behaviour of 'guestFamily' detection.\"\n        default: false\n        type: bool\n        required: false\nextends_documentation_fragment:\n- community.vmware.vmware.documentation\n\nauthor:\n    - Mike Klebolt (@MikeKlebolt) <michael.klebolt@centurylink.com>\n'''\n\nEXAMPLES = r'''\n- name: Get VM UUID\n  vmware_guest_facts:\n    hostname: \"{{ vcenter_hostname }}\"\n    username: \"{{ vcenter_username }}\"\n    password: \"{{ vcenter_password }}\"\n    datacenter: \"{{ datacenter }}\"\n    folder: \"/{{datacenter}}/vm\"\n    name: \"{{ vm_name }}\"\n  delegate_to: localhost\n  register: vm_facts\n\n- name: Upgrade VMware Tools using uuid\n  community.vmware.vmware_guest_tools_upgrade:\n    hostname: \"{{ vcenter_hostname }}\"\n    username: \"{{ vcenter_username }}\"\n    password: \"{{ vcenter_password }}\"\n    datacenter: \"{{ datacenter_name }}\"\n    uuid: \"{{ vm_facts.instance.hw_product_uuid }}\"\n  delegate_to: localhost\n\n- name: Upgrade VMware Tools using MoID\n  community.vmware.vmware_guest_tools_upgrade:\n    hostname: \"{{ vcenter_hostname }}\"\n    username: \"{{ vcenter_username }}\"\n    password: \"{{ vcenter_password }}\"\n    datacenter: \"{{ datacenter_name }}\"\n    moid: vm-42\n  delegate_to: localhost\n'''\n\nRETURN = r''' # '''\n\n\nfrom ansible.module_utils.basic import AnsibleModule\nfrom ansible_collections.community.vmware.plugins.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task\nfrom ansible.module_utils._text import to_native\n\n\nclass PyVmomiHelper(PyVmomi):\n    def __init__(self, module):\n        super(PyVmomiHelper, self).__init__(module)\n\n    def upgrade_tools(self, vm):\n        result = {'failed': False, 'changed': False, 'msg': ''}\n        # Exit if VMware tools is already up to date\n        if vm.guest.toolsStatus == \"toolsOk\":\n            result.update(\n                changed=False,\n                msg=\"VMware tools is already up to date\",\n            )\n            return result\n\n        # Fail if VM is not powered on\n        elif vm.summary.runtime.powerState != \"poweredOn\":\n            result.update(\n                failed=True,\n                msg=\"VM must be powered on to upgrade tools\",\n            )\n            return result\n\n        # Fail if VMware tools is either not running or not installed\n        elif vm.guest.toolsStatus in [\"toolsNotRunning\", \"toolsNotInstalled\"]:\n            result.update(\n                failed=True,\n                msg=\"VMware tools is either not running or not installed\",\n            )\n            return result\n\n        # If vmware tools is out of date, check major OS family\n        # Upgrade tools on Linux and Windows guests\n        elif vm.guest.toolsStatus == \"toolsOld\":\n            try:\n                force = self.module.params.get('force_upgrade')\n                if force or vm.guest.guestFamily in [\"linuxGuest\", \"windowsGuest\"]:\n                    task = vm.UpgradeTools()\n                    changed, err_msg = wait_for_task(task)\n                    result.update(changed=changed, msg=to_native(err_msg))\n                else:\n                    result.update(msg='Guest Operating System is other than Linux and Windows.')\n                return result\n            except Exception as exc:\n                result.update(\n                    failed=True,\n                    msg='Error while upgrading VMware tools %s' % to_native(exc),\n                )\n                return result\n        else:\n            result.update(\n                failed=True,\n                msg=\"VMware tools could not be upgraded\",\n            )\n            return result\n\n\ndef main():\n    argument_spec = vmware_argument_spec()\n    argument_spec.update(\n        name=dict(type='str'),\n        name_match=dict(type='str', choices=['first', 'last'], default='first'),\n        uuid=dict(type='str'),\n        moid=dict(type='str'),\n        folder=dict(type='str'),\n        datacenter=dict(type='str', required=True),\n        force_upgrade=dict(type='bool', default=False),\n    )\n    module = AnsibleModule(\n        argument_spec=argument_spec,\n        required_one_of=[\n            ['name', 'uuid', 'moid']\n        ]\n    )\n\n    if module.params['folder']:\n        # FindByInventoryPath() does not require an absolute path\n        # so we should leave the input folder path unmodified\n        module.params['folder'] = module.params['folder'].rstrip('/')\n\n    pyv = PyVmomiHelper(module)\n    # Check if the VM exists before continuing\n    vm = pyv.get_vm()\n\n    # VM already exists\n    if vm:\n        try:\n            result = pyv.upgrade_tools(vm)\n            if result['changed']:\n                module.exit_json(changed=result['changed'])\n            elif result['failed']:\n                module.fail_json(msg=result['msg'])\n            else:\n                module.exit_json(msg=result['msg'], changed=result['changed'])\n        except Exception as exc:\n            module.fail_json(msg='Unknown error: %s' % to_native(exc))\n    else:\n        vm_id = module.params.get('uuid') or module.params.get('name') or module.params.get('moid')\n        module.fail_json(msg='Unable to find VM %s' % vm_id)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "plugins/modules/vmware_guest_tools_upgrade.py"}], "after_files": [{"content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n\n# Copyright: (c) 2018, Mike Klebolt  <michael.klebolt@centurylink.com>\n# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)\n# SPDX-License-Identifier: GPL-3.0-or-later\n\nfrom __future__ import (absolute_import, division, print_function)\n__metaclass__ = type\n\n\nDOCUMENTATION = r'''\n---\nmodule: vmware_guest_tools_upgrade\nshort_description: Module to upgrade VMTools\ndescription:\n    - This module upgrades the VMware Tools on Windows and Linux guests and reboots them.\nnotes:\n    - \"In order to upgrade VMTools, please power on virtual machine before hand - either 'manually' or\n      using module M(community.vmware.vmware_guest_powerstate).\"\noptions:\n   name:\n        description:\n            - Name of the virtual machine to work with.\n            - 'This is required if O(uuid) or O(moid) is not supplied.'\n        type: str\n   name_match:\n        description:\n            - If multiple virtual machines matching the name, use the first or last found.\n        default: 'first'\n        choices: ['first', 'last']\n        type: str\n   uuid:\n        description:\n            - \"UUID of the instance to manage if known, this is VMware's unique identifier.\"\n            - This is required if O(name) or O(moid) is not supplied.\n        type: str\n   moid:\n        description:\n            - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance.\n            - This is required if O(name) or O(uuid) is not supplied.\n        type: str\n   folder:\n        description:\n            - Destination folder, absolute or relative path to find an existing guest.\n            - This is required, if O(name) is supplied.\n            - \"The folder should include the datacenter. ESX's datacenter is ha-datacenter\"\n            - 'Examples:'\n            - '   folder: /ha-datacenter/vm'\n            - '   folder: ha-datacenter/vm'\n            - '   folder: /datacenter1/vm'\n            - '   folder: datacenter1/vm'\n            - '   folder: /datacenter1/vm/folder1'\n            - '   folder: datacenter1/vm/folder1'\n            - '   folder: /folder1/datacenter1/vm'\n            - '   folder: folder1/datacenter1/vm'\n            - '   folder: /folder1/datacenter1/vm/folder2'\n        type: str\n   datacenter:\n        description:\n            - Destination datacenter where the virtual machine exists.\n        required: true\n        type: str\n   force_upgrade:\n        description:\n            - This flag overrides the guest operating system detection and forcibly upgrade VMware tools or open-vm-tools.\n            - \"This is useful when VMware tools is too old and unable to detect the 'guestFamily' value.\"\n            - 'Using this flag may sometime give unexpected results since module will override the default'\n            - \"behaviour of 'guestFamily' detection.\"\n        default: false\n        type: bool\n        required: false\n   installer_options:\n        version_added: '4.1.0'\n        description:\n            - Command line options passed to the installer to modify the installation procedure for tools.\n        type: str\n        required: false\nextends_documentation_fragment:\n- community.vmware.vmware.documentation\n\nauthor:\n    - Mike Klebolt (@MikeKlebolt) <michael.klebolt@centurylink.com>\n'''\n\nEXAMPLES = r'''\n- name: Get VM UUID\n  vmware_guest_facts:\n    hostname: \"{{ vcenter_hostname }}\"\n    username: \"{{ vcenter_username }}\"\n    password: \"{{ vcenter_password }}\"\n    datacenter: \"{{ datacenter }}\"\n    folder: \"/{{datacenter}}/vm\"\n    name: \"{{ vm_name }}\"\n  delegate_to: localhost\n  register: vm_facts\n\n- name: Upgrade VMware Tools using uuid\n  community.vmware.vmware_guest_tools_upgrade:\n    hostname: \"{{ vcenter_hostname }}\"\n    username: \"{{ vcenter_username }}\"\n    password: \"{{ vcenter_password }}\"\n    datacenter: \"{{ datacenter_name }}\"\n    uuid: \"{{ vm_facts.instance.hw_product_uuid }}\"\n  delegate_to: localhost\n\n- name: Upgrade VMware Tools using MoID\n  community.vmware.vmware_guest_tools_upgrade:\n    hostname: \"{{ vcenter_hostname }}\"\n    username: \"{{ vcenter_username }}\"\n    password: \"{{ vcenter_password }}\"\n    datacenter: \"{{ datacenter_name }}\"\n    moid: vm-42\n  delegate_to: localhost\n'''\n\nRETURN = r''' # '''\n\n\nfrom ansible.module_utils.basic import AnsibleModule\nfrom ansible_collections.community.vmware.plugins.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task\nfrom ansible.module_utils._text import to_native\n\n\nclass PyVmomiHelper(PyVmomi):\n    def __init__(self, module):\n        super(PyVmomiHelper, self).__init__(module)\n\n    def upgrade_tools(self, vm):\n        result = {'failed': False, 'changed': False, 'msg': ''}\n        # Exit if VMware tools is already up to date\n        if vm.guest.toolsStatus == \"toolsOk\":\n            result.update(\n                changed=False,\n                msg=\"VMware tools is already up to date\",\n            )\n            return result\n\n        # Fail if VM is not powered on\n        elif vm.summary.runtime.powerState != \"poweredOn\":\n            result.update(\n                failed=True,\n                msg=\"VM must be powered on to upgrade tools\",\n            )\n            return result\n\n        # Fail if VMware tools is either not running or not installed\n        elif vm.guest.toolsStatus in [\"toolsNotRunning\", \"toolsNotInstalled\"]:\n            result.update(\n                failed=True,\n                msg=\"VMware tools is either not running or not installed\",\n            )\n            return result\n\n        # If vmware tools is out of date, check major OS family\n        # Upgrade tools on Linux and Windows guests\n        elif vm.guest.toolsStatus == \"toolsOld\":\n            try:\n                force = self.module.params.get('force_upgrade')\n                installer_options = self.module.params.get('installer_options')\n                if force or vm.guest.guestFamily in [\"linuxGuest\", \"windowsGuest\"]:\n                    if installer_options is not None:\n                        task = vm.UpgradeTools(installer_options)\n                    else:\n                        task = vm.UpgradeTools()\n                    changed, err_msg = wait_for_task(task)\n                    result.update(changed=changed, msg=to_native(err_msg))\n                else:\n                    result.update(msg='Guest Operating System is other than Linux and Windows.')\n                return result\n            except Exception as exc:\n                result.update(\n                    failed=True,\n                    msg='Error while upgrading VMware tools %s' % to_native(exc),\n                )\n                return result\n        else:\n            result.update(\n                failed=True,\n                msg=\"VMware tools could not be upgraded\",\n            )\n            return result\n\n\ndef main():\n    argument_spec = vmware_argument_spec()\n    argument_spec.update(\n        name=dict(type='str'),\n        name_match=dict(type='str', choices=['first', 'last'], default='first'),\n        uuid=dict(type='str'),\n        moid=dict(type='str'),\n        folder=dict(type='str'),\n        datacenter=dict(type='str', required=True),\n        force_upgrade=dict(type='bool', default=False),\n        installer_options=dict(type='str'),\n    )\n    module = AnsibleModule(\n        argument_spec=argument_spec,\n        required_one_of=[\n            ['name', 'uuid', 'moid']\n        ]\n    )\n\n    if module.params['folder']:\n        # FindByInventoryPath() does not require an absolute path\n        # so we should leave the input folder path unmodified\n        module.params['folder'] = module.params['folder'].rstrip('/')\n\n    pyv = PyVmomiHelper(module)\n    # Check if the VM exists before continuing\n    vm = pyv.get_vm()\n\n    # VM already exists\n    if vm:\n        try:\n            result = pyv.upgrade_tools(vm)\n            if result['changed']:\n                module.exit_json(changed=result['changed'])\n            elif result['failed']:\n                module.fail_json(msg=result['msg'])\n            else:\n                module.exit_json(msg=result['msg'], changed=result['changed'])\n        except Exception as exc:\n            module.fail_json(msg='Unknown error: %s' % to_native(exc))\n    else:\n        vm_id = module.params.get('uuid') or module.params.get('name') or module.params.get('moid')\n        module.fail_json(msg='Unable to find VM %s' % vm_id)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "plugins/modules/vmware_guest_tools_upgrade.py"}]}