简体   繁体   中英

How to mount multiple disks in a loop using ansible

I just started working with Ansible recently. I am trying to mount 4 disks on azure VM which were attached using terraform. Each disk was passed with a LUN number and I am fetching the device name(sdc,sdd etc.) for each disk using that LUN no.and grep.

    - name: get volume name
      shell: echo "/dev/$(ls -l /dev/disk/azure/scsi1 |grep {{ item.lun }}|egrep -o "([^\/]+$)")"
      register: volumename
    - parted:
        device: "{{ volumename.stdout }}"
        number: 1
        state: present
    - filesystem:
        fstype: xfs
        dev: "{{ volumename.stdout }}"
    - mount:
        fstype: xfs
        opts: noatime
        src: "{{ volumename.stdout }}"
        path: "{{ item.mountpoint }}"
        state: mounted
    - command: blkid -s UUID -o value {{ volumename.stdout }}
      register: volumename_disk

    - blockinfile:
        path: /etc/fstab
        state: present
        block: |
          UUID={{ volumename_disk.stdout }}   {{ volumename.stdout }}      xfs defaults,noatime,nofail 0 0

      loop:
        - { lun: 'lun0', mountpoint: '/apps/mysql/binlog', diskname: 'binlog' }
        - { lun: 'lun1', mountpoint: '/apps/mysql/innodb', diskname: 'innodb' }
        - { lun: 'lun2', mountpoint: '/apps/mysql/data', diskname: 'data' }
        - { lun: 'lun3', mountpoint: '/apps/mysql', diskname: 'backup' }
      tags: test

I keep getting volumename variable is not defined error. Is there any way to set volumename as global so that the next playbook can access it or How I can improve this code?

First of all I'm not an expert with ansible, but what it look like you're trying to do is:

  • Use the same loop for multiple tasks.

Which I think is not possible. The other thing is that the loop -variables is only available to the task with matching indentation, in your case: blockinfile .

What you can do is create an own task -file for the tasks you want perform and include that in your playbook (loop over includes). This has been done by @Konstantin in following example: Multiple ansible task with same loop

EXTRA:
Reason why it is NOT available
IF it had been possible to use a single loop for several tasks, then you would have to make sure to apply it to all the tasks, like:

- block:
    task1
     ...
    task2
     ...
  loop:
    - { lun: 'lun0', mountpoint: '/apps/mysql/binlog', diskname: 'binlog' }
    - { lun: 'lun1', mountpoint: '/apps/mysql/innodb', diskname: 'innodb' }

EXAMPLE:

(Created an example from your comment, I do not think this is a good solution, but it is a solution) Create a list using set_fact and then pass this list to another playbook.
Using my existing examples:

my_tasks.yml :

---
- command: echo "{{ item.lun}}"
  register: volumename
- set_fact:
    volumenames: "{{ volumenames|default([]) + [ { 'name': volumename.stdout } ] }}"

- debug:
    msg: "VOLUMENAME is: {{ volumename.stdout }}"

playbook.yml :

---
- hosts: localhost
  tasks:
    - include_tasks:   my_tasks.yml
      loop:
        - { lun: 'lun0', mountpoint: '/apps/mysql/binlog', diskname: 'binlog' }
        - { lun: 'lun1', mountpoint: '/apps/mysql/innodb', diskname: 'innodb' }
        - { lun: 'lun2', mountpoint: '/apps/mysql/data', diskname: 'data' }
        - { lun: 'lun3', mountpoint: '/apps/mysql', diskname: 'backup' }

- import_playbook: playbook2.yml myvar='{{ volumenames }}'

playbook2.yml

---
- hosts: localhost
  tasks:
    - debug:
        msg: "{{ myvar }}"


After reading through documentation, I was able to find a way to achieve this.

The right approach would be to use Ansible's dictionary variable.

 raid_config: - lun: "{{ backup_lun }}" mountpoint: "{{ backup_mountpoint }}" - lun: "{{ data_lun }}" mountpoint: "{{ data_mountpoint }}" - lun: "{{ binlog_lun }}" mountpoint: "{{ binlog_mountpoint }}" - lun: "{{ innodb_lun }}" mountpoint: "{{ innodb_mountpoint }}"

Moved the tasks to a separate file mountdisk.yml and passed a dictionary to the tasks like this

 - include_tasks: "mountdisk.yml" loop: "{{ raid_config }}" loop_control: loop_var: disk tags: test
This way I was able to fetch lun and mount point as disk.lun and disk.mountpoint. Note: you would need to pass tags keyword separately in each task (if you are using one)while using include_tasks option.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM