diff options
author | Christian Pointner <equinox@spreadspace.org> | 2024-01-11 23:31:54 +0100 |
---|---|---|
committer | Christian Pointner <equinox@spreadspace.org> | 2024-01-11 23:31:54 +0100 |
commit | b439a44bc80cac4e8671b776406f4259e8ce06d1 (patch) | |
tree | 4c470484091578fb01bf5836c5c8df906583f452 /roles/storage/zfs | |
parent | storage/lvm/base: allow global volumes (diff) |
make generic use of storage/zfs, storage/lvm and storage/directory possible
Diffstat (limited to 'roles/storage/zfs')
-rw-r--r-- | roles/storage/zfs/base/defaults/main.yml | 30 | ||||
-rw-r--r-- | roles/storage/zfs/base/filter_plugins/zfs.py | 43 | ||||
-rw-r--r-- | roles/storage/zfs/base/tasks/main.yml | 9 | ||||
-rw-r--r-- | roles/storage/zfs/volume/defaults/main.yml | 5 | ||||
-rw-r--r-- | roles/storage/zfs/volume/tasks/main.yml | 46 |
5 files changed, 111 insertions, 22 deletions
diff --git a/roles/storage/zfs/base/defaults/main.yml b/roles/storage/zfs/base/defaults/main.yml index 1566890d..df56f0c8 100644 --- a/roles/storage/zfs/base/defaults/main.yml +++ b/roles/storage/zfs/base/defaults/main.yml @@ -17,3 +17,33 @@ zfs_pool_default_properties: # properties: # ashift: 12 # prop: value + +zfs_volumes: {} + +# zfs_volumes: +# storage: +# test: +# properties: +# quota: 1G +# bar: +# properties: +# quota: 4G +# children: +# blub: +# properties: +# quota: 3G +# xattr: sa +# acltype: posix +# hugo: +# properties: +# mountpoint: /var/lib/hugo +# quota: 2G +# children: +# ben: {} +# after: +# properties: +# quota: 100M +# test: +# sub1: +# properties: +# quota: 512M diff --git a/roles/storage/zfs/base/filter_plugins/zfs.py b/roles/storage/zfs/base/filter_plugins/zfs.py new file mode 100644 index 00000000..a336c197 --- /dev/null +++ b/roles/storage/zfs/base/filter_plugins/zfs.py @@ -0,0 +1,43 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from functools import partial +from copy import deepcopy + +from ansible import errors + + +def _recurse_pool_volumes(pool, prefix, volumes): + result = [] + if prefix != '': + prefix = prefix + '/' + for name, volume in volumes.items(): + entry = deepcopy(volume) + entry.pop('children', None) + entry['pool'] = pool + entry['name'] = prefix+name + result.append(entry) + if 'children' in volume: + result = result + _recurse_pool_volumes(pool, entry['name'], volume['children']) + + return result + + +def zfs_volume_list(data): + try: + result = [] + for pool, volumes in data.items(): + result = result + _recurse_pool_volumes(pool, '', volumes) + return result + except Exception as e: + raise errors.AnsibleFilterError("zfs_volume_list(): %s" % str(e)) + + +class FilterModule(object): + + filter_map = { + 'zfs_volume_list': zfs_volume_list, + } + + def filters(self): + return self.filter_map diff --git a/roles/storage/zfs/base/tasks/main.yml b/roles/storage/zfs/base/tasks/main.yml index 99b8e228..b731bb1f 100644 --- a/roles/storage/zfs/base/tasks/main.yml +++ b/roles/storage/zfs/base/tasks/main.yml @@ -59,3 +59,12 @@ label: "{{ item.key }}" when: item.key not in zfs_existing_pools command: "zpool create -m {{ item.value.mountpoint }} {% for prop, value in (item.value.properties | default(zfs_pool_default_properties)).items() %}-o {{ prop }}={{ value }} {% endfor %}{{ item.key }} {{ item.value.create_vdevs }}" + +- name: create zfs volumes + loop: "{{ zfs_volumes | zfs_volume_list }}" + loop_control: + label: "{{ item.pool }}/{{ item.name }}" + vars: + zfs_volume: "{{ item }}" + include_role: + name: storage/zfs/volume diff --git a/roles/storage/zfs/volume/defaults/main.yml b/roles/storage/zfs/volume/defaults/main.yml index bb1c0c6d..8b799655 100644 --- a/roles/storage/zfs/volume/defaults/main.yml +++ b/roles/storage/zfs/volume/defaults/main.yml @@ -1,13 +1,12 @@ --- # zfs_volume: # parent: -# type: zfs # ... # pool: tank -# name: foo/bar +# name: bar # properties: # quota: 10G -# dest: /srv/foo/bar +# dest: /srv/bar # mode: 0750 # owner: root # group: users diff --git a/roles/storage/zfs/volume/tasks/main.yml b/roles/storage/zfs/volume/tasks/main.yml index 260d706d..07a70dfc 100644 --- a/roles/storage/zfs/volume/tasks/main.yml +++ b/roles/storage/zfs/volume/tasks/main.yml @@ -1,37 +1,45 @@ --- -- name: check volume parent - when: "'parent' in zfs_volume" - assert: - msg: "the volume parent must be of type zfs and must not have a parent" - that: - - zfs_volume.parent.type == 'zfs' - - "'parent' not in zfs_volume.parent" +- name: compute full zfs volume path + set_fact: + zfs_volume_path_full: "{{ ('parent' in zfs_volume) | ternary((zfs_volume.parent.pool | default(''))~'/'~(zfs_volume.parent.name | default('')), zfs_volume.pool) }}/{{ zfs_volume.name }}" - name: create zfs dataset zfs: - name: "{{ ('parent' in zfs_volume) | ternary((zfs_volume.parent.pool | default(''))~'/'~(zfs_volume.parent.name | default('')), zfs_volume.pool) }}/{{ zfs_volume.name }}" + name: "{{ zfs_volume_path_full }}" extra_zfs_properties: "{{ zfs_volume.properties | dehumanize_zfs_properties | default(omit) }}" state: present -- name: compute derivated mountpoint +- name: gather volume mountpoint info + zfs_facts: + name: "{{ zfs_volume_path_full }}" + properties: mountpoint + register: zfs_volume_info + +- name: export volume mountpoint set_fact: - zfs_volume_mountpoint: "{{ (zfs_pools[zfs_volume.parent.pool | default(zfs_volume.pool)].mountpoint, ('parent' in zfs_volume) | ternary((zfs_volume.parent.name | default('')), ''), zfs_volume.name) | path_join }}" + storage_volume_mountpoint: "{{ zfs_volume_info.ansible_facts.ansible_zfs_datasets[0].mountpoint }}" -- name: bind mount filesystem +- name: bind mount volume when: - "'dest' in zfs_volume" - - zfs_volume.dest != zfs_volume_mountpoint - mount: - src: "{{ zfs_volume_mountpoint }}" - path: "{{ zfs_volume.dest }}" - fstype: none - opts: bind,x-systemd.automount,nofail - state: mounted + - zfs_volume.dest != storage_volume_mountpoint + block: + - name: create bind mount + mount: + src: "{{ zfs_volume_info.ansible_facts.ansible_zfs_datasets[0].mountpoint }}" + path: "{{ zfs_volume.dest }}" + fstype: none + opts: bind,x-systemd.automount,nofail + state: mounted + + - name: update volume mountpoint + set_fact: + storage_volume_mountpoint: "{{ zfs_volume.dest }}" - name: set volume owner/group and mode file: state: directory - path: "{{ zfs_volume.dest | default(zfs_volume_mountpoint) }}" + path: "{{ storage_volume_mountpoint }}" mode: "{{ zfs_volume.mode | default(omit) }}" owner: "{{ zfs_volume.owner | default(omit) }}" group: "{{ zfs_volume.group | default(omit) }}" |