Each Ansible task in playbook takes 10s to even start - ansible

I run the script from AnsibleTower and use WinRM to execute it on a Windows machine.
This script just creates a directory. It takes 8-10s to run it.
In some completely different environments, it takes < 1s.
What could be wrong in the environment where it takes 8-10s to run each of these tasks?
- hosts: the_test_host
tasks:
- name: Create 1st file
win_file:
path: D:\test_1.txt
state: touch
- name: Create 2nd file
win_file:
path: D:\test_2.txt
state: touch
- name: Create 3rd file
win_file:
path: D:\test_3.txt
state: touch
- name: Create 4th file
win_file:
path: D:\test_4.txt
state: touch
- name: Create 5th file
win_file:
path: D:\test_5.txt
state: touch

The main source of playbook start slowdown is fact gathering. Turn it off:
- hosts: the_test_host
gather_facts: false
tasks:
...
The other issues may be with network (latency), gss pam module (for centos; disable it if you can).
If you are desperate for speed, you can try to use connection multiplexing and mitogen, but both would require a decent amount of attention and will yield few unpleasant surprises.

Related

How can I manage groups in inventory?

I have a common playbook (task) but in my last task I want to do an action on a group of hosts and when it is finished, do the same action on another group (for my test I simply empty a folder):
- name: test clean folder on hosts
ansible.builtin.file:
path: /testJO
when: inventory_hostname in groups['c_hosts']
- name: test clean folder on master
ansible.builtin.file:
path: /testJO
when: inventory_hostname in groups['master’]
I have issue with my inventory file :
/root/ansible_Folder/inventories/inventories.yml :
all:
hosts:
children:
master:
hosts:
dem-master:
c_hosts:
hosts:
dem-host:
Who knows how I can manage my inventories file please?
EDIT :
I tried your solution which seems to me coherent but i have this error message :
ERROR! conflicting action statements: hosts, tasks
The error appears to be in '/root/ansible-cortex-lab/playbooks/roles/cortex/tasks/main.yml': line 1, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- hosts: c_hosts
^ here
I just copy past both config file you gave to me.
Do you know why I have this behaviour please ?
Separate the plays, e.g.
- hosts: c_hosts
tasks:
- name: test remove folder
ansible.builtin.file:
path: /testJO
state: absent
- name: test create folder
ansible.builtin.file:
path: /testJO
state: directory
- hosts: master
tasks:
- name: test remove folder
ansible.builtin.file:
path: /testJO
state: absent
- name: test create folder
ansible.builtin.file:
path: /testJO
state: directory
The module file can't simply clean a folder. Instead, remove a folder and create it again.
To fix the inventory, remove the 2nd line hosts:. See Inventory basics: formats, hosts, and groups
all:
children:
master:
hosts:
dem-master:
c_hosts:
hosts:
dem-host:

ERROR! 'copy' is not a valid attribute for a Play

I am trying to make ansible playbook that connects to the server via ssh and sends a file.
Most of my google search yield no concrete results.
-
become: true
hosts: all
remote_user: artur
tasks: ~
-
copy:
dest: /home/artur/grep_error.py
group: UnixUsers
mode: 420
owner: artur
src: /Users/artur/Desktop/sublime/projects/scripts/grep_error.py
name: "example copying file with owner and permissions"
I expect to copy the file over to the ssh server.
Take Y minutes to learn yaml. Pay particular attention to the fact that indentation and new lines are syntactically significant
Install yamllint and validate your yaml files. It will save you a lot of precious time
Install ansible-lint and validate your files again. This one will go over the particular ansible syntax and watch for good practice
Read the doc about playbooks and make sure you respect the syntax (i.e. understand the errors you get from valiators above).
Now I gave you some references, here is a correction of your playbook
---
- name: My first play to copy files
become: true
hosts: all
remote_user: artur
tasks:
- name: Example copying file with owner and permissions
copy:
src: /Users/artur/Desktop/sublime/projects/scripts/grep_error.py
dest: /home/artur/grep_error.py
owner: artur
group: UnixUsers
mode: 0420
- name: I'm just a dummy task to show you a play can go on
debug:
msg: I'm a dummy task

Trying to split my Ansible playbook based on the Operating System

I have a playbook which needs to be run based on the operating System.
UseCase: Lets assume there is a service that is running.
On Linux we can check if it is installed and running using the
systemctl status application.service
While command and on windows we will be using the
sc query "ServiceName" | find "RUNNING"
Now we have to install it based on the output of the above a commands which requires us to segregate the playbook based on the OS.
Classic Example: Create a directory based on the OS
- name: Install QCA Agent on Linux targets
hosts: all
gather_facts: true
remote_user: root
tasks:
- name: Create Directory for Downloading Qualys Cloud Agent
sudo: yes
sudo_user: root
file:
path: /usr/q1/
state: directory
owner: root
group: root
mode: 0777
recurse: no
- name: Create Directory for Downloading Qualys Cloud Agent
win_file:
path: c:\q1
state: directory
owner: Administrator
group: Administrator
mode: 0777
recurse: no
The playbook will alwayz be successful only if one of the condition is met and it is whether it is Windows or Unix OS. I can alwayz add a condition which will prompt based on:
when: ansible_distribution == 'Redhat' or ansible_distribution == 'CentOS'
However what i would like to achieve is based on a condition it should trigger my playbook.yml file.
name: Load a variable file based on the OS type, or a default if not found. Using free-form to specify the file.
include_vars: "{{ item }}"
with_first_found:
- "{{ ansible_distribution }}.yaml"
- "{{ ansible_os_family }}.yaml"
- default.yaml
https://docs.ansible.com/ansible/2.5/modules/include_vars_module.html?highlight=with_first_found
I would like to know if there is a better example explaining the same that i could implement or if there are other ways to achieve the same.
Thank you,
The example you show from the Ansible docs is pretty much the best practice and is common in many playbooks (and roles for that matter) that deal with multiple OSes. If you have code that is different (instead of the variable example here), you'll be using include_tasks instead of include_vars, but the concept is the same.

How to make Ansible notice host is the same and avoid task collisions

My inventory files keep the same logical number of hostsbut may differ in the number of ansible_host:
Case 1, three logical, hosts three ansible_hosts
all:
hosts:
db:
ansible_host: db.example.com
apps:
ansible_host: app.example.com
proxy:
ansible_host: proxy.example.com
Case 2, three logical, hosts one ansible_host
all:
hosts:
db: &ahost
ansible_host: allinone.example.com
apps:
<<: *ahost
proxy:
<<: *ahost
In my playbook there are some common tasks applicable for all,
like yum
- name: "Install OS packages"
yum: pkg={{item}} state=installed
with_items:
- p1
- p2
- ... (quite a lot)
they may collide when running since ansible tries to run them in parrallel which causes yum session locks.
I wonder how can I tell ansible to skip installing os packages on apps and
proxy once it has already started yum on db in Case 2.
(Other than swithcing off the parrallelism)
You can take advantage of Ansible File module. Prior to you Install OS Packages step, you can create a temporary file.
- name: "Create temporary file to lock yum"
file:
path: /tmp/yum.lock
state: present
Next, you will create a task to check if lock file exists. We expect for it to exist, once it was created during the first connection.
- name: "Check if yum lock file exists"
stat:
path: /tmp/yum.lock
register: yum_lock
Then, modify your task:
- name: "Install OS packages"
yum: pkg={{item}} state=installed
when: yum_lock.stat.exists == False
with_items:
- p1
- p2
- ... (quite a lot)
Finally, add a cleanup task to remove yum lock file.
- name: "Delete temporary file to lock yum"
file:
path: /tmp/yum.lock
state: absent

How to get facts at each command in Ansible

Ansible get facts only at start. But i need check facts at each commands.
For example:
I need create a directory, after that i need put file to this directory. But ansible get fact 'dir doesn't exist' at start, create dir and at next step fact still FALSE and ansible skip this step =( And do this step only after second run.
I'll try setup after all steps to gathering facts again but it doesn't work.
I do it like this:
- stat: path=/etc/zabbix/scripts/rabbitmq
register: rmqscriptdir
- name: Create scripts dir if not exist
when: rmqscriptdir.stat.exists == False
shell: mkdir /etc/zabbix/scripts/rabbitmq
- name: Gathering facts again
setup:
- name: Set owner and permissions to rabbitmq directory
when: rmqscriptdir.stat.exists == True
file: path=/etc/zabbix/scripts/rabbitmq owner=zabbix group=root mode=0750
- stat: path=/etc/zabbix/scripts/rabbitmq/api.py
register: rmqscript_api
- name: Create api.py if not exist
when: rmqscript_api.stat.exists == False and rmqscriptdir.stat.exists == True
shell: cd /etc/zabbix/scripts/rabbitmq; wget https://raw.githubusercontent.com/jasonmcintosh/rabbitmq-zabbix/master/scripts/rabbitmq/api.py
- name: Gathering facts again
setup:
- name: Set owner and permissions to api.py
when: rmqscript_api.stat.exists == True
file: path=/etc/zabbix/scripts/rabbitmq/api.py owner=zabbix group=root mode=0755
I think you misunderstand what the setup module does. By registering a value it does not become a fact that will be reloaded by the setup module when run again. Your registered value stays the same. If you want to check again if a path exists you do not need to re-run the setup module, but the stats module and again register its output.
But anyway, the idea of Ansible is actually to not manually check if every task should be executed or not. That is something Ansible takes care for you, Ansible in general is indepotent, meaning it will have the same result no matter how many times you run the play.
Here is a cleaned up version, which creates a folder and downloads the file. If the folder already exists, the 1st task will do nothing. If the file api.py already exists, the 2nd task will do nothing.
- name: Create scripts dir if not exist
file:
path: /etc/zabbix/scripts/rabbitmq
state: directory
owner: zabbix
group: root
mode: 0750
- name: Create api.py if not exist
get_url:
url: https://raw.githubusercontent.com/jasonmcintosh/rabbitmq-zabbix/master/scripts/rabbitmq/api.py
dest: /etc/zabbix/scripts/rabbitmq/api.py
owner: zabbix
group: root
mode: 0755
PS: If you want to see which values are reloaded by the setup module, you can register its output and show it in a debug task, like so:
- setup:
register: all_server_facts
- debug:
var: all_server_facts
This only contains server facts, info about cpu, hard drives, network etc. Also see this answer for an example output.

Resources