74

I would like to use a system fact for a host times a number/percentage as a base for a variable. What I am trying to do specifically is use the ansible_memtotal_mb value and multiply it by .80 to get a ramsize to then use in setting a Couchbase value. I have been trying different variations of the line below. I'm not ever sure that it is possible, but any help would be appreciated.

vars:
  ramsize: '"{{ ansible_memtotal_mb }}" * .80'
Flair
  • 2,609
  • 1
  • 29
  • 41
AValenti
  • 853
  • 1
  • 6
  • 7
  • 1
    Where are you trying to use this? If it's inside a template then you could use Jinja filtering directly to do this there. Unfortunately Ansible outside of templates only supports a stripped down list of Jinja filters and I don't think multiplication is covered in that. – ydaetskcoR Nov 03 '15 at 18:00
  • It is right in the playbook. It is not in a separate template. – AValenti Nov 03 '15 at 19:09
  • Yes, but how do you intend to use the variable? – ydaetskcoR Nov 03 '15 at 19:51
  • - hosts: np-couchbase_1stnode tasks: - name: Initialize the Couchbase cluster command: /opt/couchbase/bin/couchbase-cli cluster-init -c 127.0.0.1:8091 --cluster-init-ramsize= {{ ramsize}} -u Administrator -p password – AValenti Nov 03 '15 at 20:15
  • Sorry, that is the command that would get executed in the playbook. ramsize would be the calculated value based on the facts that are gathered from the host. That didn't get formatted quite right in the comment, but hopefully you get the idea. – AValenti Nov 03 '15 at 20:17

3 Answers3

113

You're really close! I use calculations to set some default java memory sizes, which is similar to what you are doing. Here's an example:

{{ (ansible_memtotal_mb*0.8-700)|int|abs }}

That shows a couple of things- first, it's using jinja math, so do the calculations inside the {{ jinja }}. Second, int and abs do what you'd expect- ensure the result is an unsigned integer.

In your case, the correct code would be:

vars:
  ramsize: "{{ ansible_memtotal_mb * 0.8 }}"
Nikolay Vasiliev
  • 5,656
  • 22
  • 31
tedder42
  • 23,519
  • 13
  • 86
  • 102
  • 4
    Thanks for the help. My final solution ended up very much like your example. I had to include the 0 before the decimal otherwise it complained. Also, the variable definition needed to be included in double quotes. I did want an integer value and it doesn't hurt to make sure that it is an absolute value. ramsize: "{{ (ansible_memtotal_mb*0.8)|int|abs }}" – AValenti Nov 04 '15 at 13:02
  • 3
    Note that in a calculation like this the `abs` doesn't add much, since the calculation will never result in a negative (unless you have negative total memory, in which case you have bigger problems). But what may be important for some use cases is to use the `round` filter in order to drop the decimal. – Scott Buchanan Aug 29 '18 at 15:19
  • 2
    If “ansible_memtotal_mb” is a string, the result will be a string, N × the_original_string. The int casting is often necessary before applying a factor. – Gaétan RYCKEBOER Nov 27 '19 at 08:47
  • To anyone who wonders about the unit: Ansible reports MiB (base 1024) on a unixoid OS and MB (base 1000) on windows. Source: https://github.com/ansible/ansible/issues/36463 – wedi May 28 '20 at 12:55
7

One little thing to add. If you presume the math multiplication has precedence before jinja filter (| sign), you're wrong ;-)

With values like

total_rate: 150
host_ratio: 14 # percentual

"{{ total_rate*host_ratio*0.01|int }}" => 0 because 0.01|int = 0
"{{ (total_rate*host_ratio*0.01)|int) }}" => 21 as one expects
dosmanak
  • 386
  • 2
  • 11
0

use: {{ ansible_memtotal_mb|int * 0.8 - 700 }}

Victor Behar
  • 740
  • 6
  • 9