# Run a command only on hosts that have low CPU usage

**URL:** <https://forum.ansible.com/t/run-a-command-only-on-hosts-that-have-low-cpu-usage/32094>\
**Category:** Ansible Project\
**Created:** [January 30, 2020, 12:48am UTC](https://forum.ansible.com/t/run-a-command-only-on-hosts-that-have-low-cpu-usage/32094 "2020-01-30T00:48:58Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Eric\_S](https://avatars.discourse-cdn.com/v4/letter/e/aca169/32.png) [@Eric\_S](https://forum.ansible.com/u/Eric_S)\
**Post date:** [January 30, 2020, 12:48am UTC](https://forum.ansible.com/t/run-a-command-only-on-hosts-that-have-low-cpu-usage/32094/1 "2020-01-30T00:48:58Z")

</div>

Hi Folks,  
I am looking for a simple way to have Ansible perform the following automation for me:

1. From a set of N hosts, find out which host has the lowest CPU usage at the moment
2. Run a command on **only that host**.  
This pattern could be extended to a general case of:

> Run a command on a subset of hosts matching a condition which is not static.

This could apply for the following types of use cases:

- Find out which hosts are running low on disk space, and only expand disk space on the hosts which are running low
- Find out which hosts are lacking a particular upgrade, and only upgrade those hosts
- Only run a command on machines which are not currently under heavy load  
This seems like a common and desirable enough pattern, but as far as I can tell there is not a well defined way to execute this with Ansible. Is there a simple way to do this with a playbook, or do I need to write a strategy plugin?

Thanks,  
Eric

---

<div class="post-metadata">

**Author:** ![racke](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/racke/32/4767_2.png) [@racke](https://forum.ansible.com/u/racke)\
**Post date:** [January 30, 2020, 6:27am UTC](https://forum.ansible.com/t/run-a-command-only-on-hosts-that-have-low-cpu-usage/32094/2 "2020-01-30T06:27:33Z")

</div>

> Hi Folks,  
> I am looking for a simple way to have Ansible perform the following automation for me:
> 
> 1. From a set of N hosts, find out which host has the lowest CPU usage at the moment  
> 2. Run a command on \*only that host\*.
> 
> This pattern could be extended to a general case of:
> 
> &nbsp;&nbsp;&nbsp;&nbsp;Run a command on a subset of hosts matching a condition which is not static.
> 
> This could apply for the following types of use cases:
> 
> &nbsp;&nbsp;\* Find out which hosts are running low on disk space, and only expand disk space on the hosts which are running low  
> &nbsp;&nbsp;\* Find out which hosts are lacking a particular upgrade, and only upgrade those hosts  
> &nbsp;&nbsp;\* Only run a command on machines which are not currently under heavy load
> 
> This seems like a common and desirable enough pattern, but as far as I can tell there is not a well defined way to  
> execute this with Ansible. Is there a simple way to do this with a playbook, or do I need to write a strategy plugin?
> 
> Thanks,  
> Eric

Hello Eric,

you could try to add the hosts to a new group with the "add\_host" module and execute the command with delegate\_to in  
a loop over the hosts in that group.

Regards  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Racke

---

<div class="post-metadata">

**Author:** ![Eric\_S](https://avatars.discourse-cdn.com/v4/letter/e/aca169/32.png) [@Eric\_S](https://forum.ansible.com/u/Eric_S)\
**Post date:** [January 30, 2020, 4:24pm UTC](https://forum.ansible.com/t/run-a-command-only-on-hosts-that-have-low-cpu-usage/32094/3 "2020-01-30T16:24:14Z")

</div>

Racke,  
Thanks for your response.

In practice, what would this look like?

So far, I have a playbook that I can use to get a list of CPU values. However, I am having trouble correlating the value of CPU to its corresponding hostname.

---

<div class="post-metadata">

**Author:** ![racke](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/racke/32/4767_2.png) [@racke](https://forum.ansible.com/u/racke)\
**Post date:** [January 30, 2020, 4:42pm UTC](https://forum.ansible.com/t/run-a-command-only-on-hosts-that-have-low-cpu-usage/32094/4 "2020-01-30T16:42:26Z")

</div>

> Racke,  
> Thanks for your response.
> 
> In practice, what would this look like?
> 
> So far, I have a playbook that I can use to get a list of CPU values. However, I am having trouble correlating the value  
> of CPU to its corresponding hostname.
> 
> ---  
> - hosts: host\_list  
> gather\_facts: false
> 
> tasks:  
> - name: Get CPU usage  
> shell: "top -b -n 1 | head -n3 | tail -n1 | awk '{print $2}'"  
> register: top
> 
> - name: Set CPU fact  
> set\_fact:  
> cpu\_list: "{{ ansible\_play\_hosts | map('extract', hostvars, 'top') | map(attribute='stdout') | list }}"
> 
> Is this on the right track, or do I want a different approach entirely?
> 
> Thanks,  
> Eric

Hello Eric,

this can be done, but I doubt that it makes sense to do it with Ansible as above (especially with a lot of hosts).

Collect system metrics on each server with something like Telegraf and base your decisions on that.

Regards  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Racke

---

<div class="post-metadata">

**Author:** ![vbotka](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/vbotka/32/359_2.png) [@vbotka](https://forum.ansible.com/u/vbotka)\
**Post date:** [January 30, 2020, 6:07pm UTC](https://forum.ansible.com/t/run-a-command-only-on-hosts-that-have-low-cpu-usage/32094/5 "2020-01-30T18:07:59Z")

</div>

Create list of dictionaries

&nbsp;&nbsp;- name: Set CPU fact  
&nbsp;&nbsp;&nbsp;&nbsp;set\_fact:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cpu\_list: "{{ ansible\_play\_hosts|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map('extract', hostvars)|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list\>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;json\_query('.{host: inventory\_hostname,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cpu: top.stdout}') }}"  
&nbsp;&nbsp;&nbsp;&nbsp;run\_once: true

Find the minimal load

&nbsp;&nbsp;- set\_fact:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cpu\_min: "{{ cpu\_list|json\_query('.cpu')|min }}"  
&nbsp;&nbsp;&nbsp;&nbsp;run\_once: true

and find the host with this minimal load

&nbsp;&nbsp;- set\_fact:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host\_min: "{{ cpu\_list|json\_query(query)|first }}"  
&nbsp;&nbsp;&nbsp;&nbsp;vars:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query: "[?cpu == '{{ cpu\_min }}'].host"  
&nbsp;&nbsp;&nbsp;&nbsp;run\_once: true

HTH,

&nbsp;&nbsp;-vlado
