1

I'm struggling with 1 ansible role. I'm trying to make a role with 2 vars, extra space to add to the volume, and the mount point for example "/disco1" and "1.5g"

Using lvextend to extend my logical volume works, but when you need to add more space you need to get the correct logical volume total size and add the extra space to add. Tasks of the role:

---
- name: Set device name fact
  set_fact:
   device_path : "{{ item.device}}"
  with_items: "{{ansible_mounts}}"
  when: "fs_name in item.mount"
    
- name: Set device name fact
  set_fact:
   device_name : "{{ item.device.split('/')[-1]}}"
  with_items: "{{ansible_mounts}}"
  when: "fs_name in item.mount"
    
     
- name: Set Volume group fact
  set_fact:
   vg_name : "{{ device_name.split('-')[0]}}"
    
    
- name: Set Logical volume fact
  set_fact:
   lv_name : "{{ device_name.split('-')[1]}}"
    
- name: Get current lv space
  shell:  lvs --noheadings -o lv_size '{{ vg_name }}/{{lv_name}}'| sed 's/g//'
  register: lv_size
  no_log: true
- name: debug lv size
  debug:
    msg: "{{lv_size.stdout_lines}}"
    
- name: extend fs
  lvol:
    vg: "{{vg_name}}"
    lv: "{{lv_name}}"
    size: "{{lv_size.stdout_lines  | int  + fs_size_add |int  }}"
    resizefs: yes

Default file: main.yml

---
fs_name: /disco1
fs_size_add: '1.4G'

The problem is that I'm not being able to get the current disk size correctly as an integer to add the desired size to add and the current size.

After all the struggles and with the immense help of the user toydarian there is my role:

tasks/main.yml

    ---
    - name: Set device name fact
      set_fact:
       device_path : "{{ item.device}}"
      with_items: "{{ansible_mounts}}"
      when: "fs_name in item.mount"
    
    
    - set_fact:
       device_name : "{{ item.device.split('/')[-1]}}"
      with_items: "{{ansible_mounts}}"
      when: "fs_name in item.mount"
    
    - name: Set Volume group fact
      set_fact:
       vg_name : "{{ device_name.split('-')[0]}}"
    
    
    - name: Set Logical volume fact
      set_fact:
       lv_name : "{{ device_name.split('-')[1]}}"
    - shell: |
        lvs --noheadings -o lv_size '{{ vg_name }}/{{lv_name}}' |  grep -oPi '\d+.\d+(?=G)'
      register: vsize
    
      #- fail:
      #   msg: "Current volume sie could not be parsed. Not in correct GB format?"
      #when: vsize_stdout | length == 0
    
    - set_fact:
        nsize: "{{ (vsize.stdout | float) + (fs_size_add  | float) }}"
    - debug:
        msg: |
          current size: "{{vsize.stdout}}"
          new size: "{{nsize}}"
    
    
    
    - name: extend fs
      lvol:
        vg: "{{vg_name}}"
        lv: "{{lv_name}}"
        size: "{{ nsize}}G"
        resizefs: yes

defaults/main.yml

    ---
    fs_name: /disco1
    fs_size_add: '0.4'
ikora
  • 772
  • 3
  • 16
  • Please tell us what is not working with your code. You only say what you are doing but not what the actual problem is. I see one error on the first glance: `stdout_lines` is a `list` ([docs](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/shell_module.html#return-values)) if you try to cast it to an `int`, you will [get 0 by default](https://jinja.palletsprojects.com/en/2.11.x/templates/#int). – toydarian Apr 16 '21 at 04:54
  • The problem is exactly that, im getting a 0 when I parse to int so when I try to extent the disk, it trie to shrink to 0 space instead of casting the 1.00 GB. – ikora Apr 16 '21 at 06:35

1 Answers1

1

Your problems are in this line: size: "{{lv_size.stdout_lines | int + fs_size_add | int }}"

  • lv_size.stdout_lines is a list. When you try to convert it to an int, it will turn out to be 0. Check the documentation.
  • '1.4G' is a string that can not be converted to an int, as it contains a character (G). So that one is 0 as well.
  • The size option actually takes a string, not an int. If it gets an int, it will convert it to a string and treat that as megabytes.

According to the documentation, it should be possible to use percentages to increase the size of a logical volume like this size: "+100%FREE" to extend the volume to use all free space.
You need to use ansible version 2.1 or newer for that to work.
See the lvcreate(8) man-page and the examples in the documentation for more details.

If you can't use percentages, this is how you can calculate the new size of the logical volume:

- shell: |
    lvs --noheadings -o lv_size '{{ vg_name }}/{{lv_name}}' | grep -oP '\d+,\d+(?=g)' | sed "s/,/./"
  register: vsize

- fail:
    msg: "Current volume size could not be parsed. Not in GB?"
  when: vsize.stdout | length == 0

- set_fact:
    nsize: "{{ (vsize.stdout | float) + (fs_size_add | float) }}"

- debug:
    msg: |
      current size: {{ vsize.stdout }}
      new size: {{ nsize }}
  • It will fail if it is not able to parse the current size. E.g. if it is in MB instead of GB.
  • fs_size_add needs to be a parsable float. E.g. 1.4, but NOT 1.4G.
toydarian
  • 4,246
  • 5
  • 23
  • 35
  • You are right it is being processed as a string. Anyways i cannot use +100%FREE because that will use all the VG space. I need to set a specific size on a variable 1.4 and then get the current space of the disk and add 1.4 to the current disk size. – ikora Apr 16 '21 at 07:17
  • In that case, you need to get the current size in GB, parse the number from it, convert it to `float`, add `1.4` to it (`float` again, not `int`) and then set `size: {{ new_size }}G` – toydarian Apr 16 '21 at 07:24
  • Yes figured that out, the thing is that I'm not able to get the current space as an integer in any way, I used ansible facts with ansible_lvm and size_g but I cannot access the desired volume. When you want to access the exact volume you need to write the volume name hardcoded you cannot set a variable inside an ansible fact like: "{{ ansible_lvm.lvs.latest.size_g}}" <- this works but the latest (the actual lv name is hardcoded and I would need something like "{{ ansible_lvm.lvs.{{lv_name}}.size_g}} (That don't work, ansible cant use variables inside facts or other variables (at my knowledge. – ikora Apr 16 '21 at 08:18
  • check out my latest edit, that explains how you can calculate the new volume size – toydarian Apr 16 '21 at 08:21
  • This approach seem to be correct, but the current size is returning nothing, I executed the lvs command directly on the machine (without ansible just bash) and its returning nothing, if think the sed and the grep are no working properly. (If i quit te grep it returns 3.00G) also the ansible task returns that: "msg": "current size: \"\"\nnew size: \"1.2\"\n\n\n\n#- name: extend fs\n# lvol:\n#vg: \"LVMvgTEST\"\n#lv: \"lvtest\"\n" – ikora Apr 16 '21 at 08:53
  • mhm, maybe the output is depending on the locale that is set. For me it returns `236,25g`. So you will need to adjust the `grep` and `sed` to match the output of the `lvs` command. The fail should trigger and abort the play when it can't parse the output, though. – toydarian Apr 16 '21 at 08:59
  • 1
    If the output is `3.00G`, you would need `grep -oP '\d+.\d+(?=G)'` and no `sed` at all – toydarian Apr 16 '21 at 09:02
  • You helped me inmensely, thats correct only with the grep it worked. And I had to write the g on lowercase, because my lvm wrote it on lower (I added -i to the grep so it doesn't need to be on a specific lower or upper case) I will add also my final roll on the question so everyone can see the working role – ikora Apr 16 '21 at 09:10