Trying to force a single task to localhost

Hi all,
First post here. I am writing a playbook which performs system patching. Prior to patching I have it check if the system is a vm and if so perform a snapshot.

Where I am getting stuck is the task that runs the snapshot needs to run on localhost where as my other task run on the remote systems.

The error im getting is failed to import python library and the reason for this is its still trying to run the snapshot module on the remote host not locally. so im not sure where Im going wrong.

Below is the 2 yaml files.
Thanks

main.yml

 ---
- name: Perform OS Pacthing
  #hosts: "{{ NODES }}"
  hosts: all
  become: yes
  vars:
    any_service_running: false
    service_list:
      - opendkim
      - postfix
      - nagios
      - mysqld
      - squid
      - rhnsd

  tasks:
    - name: Send Notification
      include_role:
        name: sendmail
      vars:
        email_subject: "OS Patching Initiated for {{ ansible_hostname }}"
      when: emailsend is defined

    - name: Patching Pre-Checks
      include_role:
        name: linux-os-patching
        tasks_from: pre-check.yml

    - name: Create VM Snapshot
      include_role:
        name: linux-os-patching
        tasks_from: vm-create-snapshot.yml
      when: ansible_virtualization_type == "VMware"

    - name: Patching
      include_role:
        name: linux-os-patching

    - name: Patching Post-Checks
      include_role:
        name: linux-os-patching
        tasks_from: post-check.yml

    - name: Send Notification
      include_role:
        name: sendmail
      vars:
         email_subject: "OS Patching COMPLETED for {{ ansible_hostname }}"
      when: emailsend is defined

vm-create-snapshot.yml

---
- name: Take Snapshot
  collections:
    -  community.vmware.vmware_guest_snapshot
  vmware_guest_snapshot:
    hostname: "{{ vcenter_hostname }}"
    username: "{{ vcenter_username }}"
    password: "{{ vcenter_password }}"
    datacenter: "{{ vcenter_datacenter }}"
    validate_certs: "{{ vcenter_validate_certs }}"
    #name: "{{ vcenter_vmname }}"
    name: "{{ ansible_hostname }}"
    state: present
    snapshot_name: "Ansible-Managed-Snapshot"
    folder: "/{{ vcenter_datacenter }}/vm/"
    description: "This snapshot is created by Ansible"
  delegate_to: localhost-py3

localhost-py3 in inventory looks like this
localhost-py3 ansible_host=localhost ansible_connection=local ansible_python_interpreter=/usr/bin/python3.9

Try this:

- name: VM Snapshot block
  when: ansible_virtualization_type == "VMware"
  delegate_to: localhost
   vars: 
     ansible_connection: local
  block: 
     - name: Create vm snapshot
      ansible.builtin.include_role:
          name: linux-os-patching
          tasks_from: vm-create-snapshot.yml


  

Thanks for the respsonse! Unfortunately still getting an error

The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_vmware_guest_snapshot_payload_s5lhy8vi/ansible_vmware_guest_snapshot_payload.zip/ansible_collections/community/vmware/plugins/module_utils/vmware.py", line 31, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'
fatal: [10.66.12.10 -> localhost-py3]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "datacenter": "TA-DR",
            "description": "This snapshot is created by Ansible",
            "folder": "/TA-DR/vm",
            "hostname": "10.66.8.49",
            "memory_dump": false,
            "moid": null,
            "name": "ans-test",
            "name_match": "first",
            "new_description": null,
            "new_snapshot_name": null,
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "port": 443,
            "proxy_host": null,
            "proxy_port": null,
            "quiesce": false,
            "remove_children": false,
            "snapshot_id": null,
            "snapshot_name": "Ansible-Managed-Snapshot",
            "state": "present",
            "use_instance_uuid": false,
            "username": "administrator@vsphere.local",
            "uuid": null,
            "validate_certs": false
        }
    },
    "msg": "Failed to import the required Python library (requests) on ansible01-ta.therap.net's Python /usr/bin/python3.9. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter"

Are you sure that it’s running on an incorrect host? Based on the output you provided it looks like it’s running on a host other than the play’s target (presumably localhost), since ansible_hostname is ans-test and the hostname in the error is ansible01-ta.

Going to ask for the sake of asking, “requests” is install on your controller host correct?

Yes its installed. if im reading this right when it drops the task to localhost seems to be where its failing and for whatever reason it almost looks like its using the wrong interpreter?

[ansible@ansible01-ta ansible]$ pip3.9 install requests
Defaulting to user installation because normal site-packages is not writeable
Requirement already satisfied: requests in /home/ansible/.local/lib/python3.9/site-packages (2.32.3)
Requirement already satisfied: charset-normalizer<4,>=2 in /home/ansible/.local/lib/python3.9/site-packages (from requests) (3.3.2)
Requirement already satisfied: idna<4,>=2.5 in /home/ansible/.local/lib/python3.9/site-packages (from requests) (3.7)
Requirement already satisfied: urllib3<3,>=1.21.1 in /home/ansible/.local/lib/python3.9/site-packages (from requests) (2.2.2)
Requirement already satisfied: certifi>=2017.4.17 in /home/ansible/.local/lib/python3.9/site-packages (from requests) (2024.6.2)
import requests
ModuleNotFoundError: No module named 'requests'
fatal: [10.66.12.10 -> localhost-py3]: FAILED! => {
    "changed": false,
"msg": "Failed to import the required Python library (requests) on ansible01-ta.therap.net's Python /usr/bin/python3.9. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter"
}

Yeah It looks like things go wrong when it drops to localhost (ansible01-ta)
so this playbook performs patching on the remote hosts in this case (ans-tst)

But the one tsk of creating a snapshot if the remote host is a vm needs to run on the localhost not the remote host thats where Im having isuues.
thanks

import requests
ModuleNotFoundError: No module named 'requests'
fatal: [10.66.12.10 -> localhost-py3]: FAILED! => {
    "changed": false,
"msg": "Failed to import the required Python library (requests) on ansible01-ta.therap.net's Python /usr/bin/python3.9. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter"
}

Okay, so your initial premise that it was running on the wrong host was incorrect. As we can see from the error, the task is running on localhost, but requests is not installed for /usr/bin/python3.9 on localhost.

You have done a user install of this library for the ansible user, but when the task runs it does not find it. This implies that the task is running as a different user, and indeed when we review the play we find that you have set become: true at the play level.

There are two ways to fix this error: disable privilege escalation for this task so that it runs as the user who already has requests installed, or install requests in a way that makes it available to the root user (the default privilege escalation target.)

1 Like

Thank you both @flowerysong & @binbashroot this is working now!!

I ended up just installing the necessary modules for python3.9 under root because the module to create the snapshot requires privilege escalation. So when i disabled the become it failed.

Thanks again I really appreciate the help!!