Skip to content

Commit 7a8e9a7

Browse files
committed
F #140: Merge back datastore IDs into ds_dict
1 parent 9fced4e commit 7a8e9a7

File tree

6 files changed

+119
-132
lines changed

6 files changed

+119
-132
lines changed

playbooks/site.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868

6969
- role: datastore/node
7070
tags: [datastore]
71-
when: ds.mode is defined and ds.mode != 'generic'
7271

7372
- role: frr/evpn
7473
tags: [network]
@@ -103,10 +102,12 @@
103102
when: *prometheus
104103

105104
- hosts: "{{ node_group | d('node') }}"
106-
tags: [node, stage4]
105+
tags: [node, stage2]
107106
collections:
108107
- opennebula.deploy
109108
roles:
109+
# NOTE: If datastore IDs are not "predicted" for the generic mode, we try to post-patch
110+
# symlinks iff IDs are merged back into the ds_dict (otherwise nothing should happen).
110111
- role: datastore/node
111112
tags: [datastore]
112113
when: ds.mode is defined and ds.mode == 'generic'
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
- name: Compute helper facts
3+
ansible.builtin.set_fact:
4+
ds_names: >-
5+
{{ hostvars[leader | d(omit)].ds_names | d(_items | map(attribute='key') | list) }}
6+
ds_dict: >-
7+
{{ hostvars[leader | d(omit)].ds_dict | d(_items | items2dict) }}
8+
vars:
9+
_ds: >-
10+
{{ ds_defaults | combine(ds.config | d({}), recursive=true) }}
11+
_items: >-
12+
{{ _ds | dict2items
13+
| map(attribute='value')
14+
| map('dict2items')
15+
| flatten
16+
| rejectattr('value.managed', 'false') }}
17+
18+
- name: Ensure /var/lib/one/datastores/ exists
19+
ansible.builtin.file:
20+
path: /var/lib/one/datastores/
21+
state: directory
22+
owner: 9869 # oneadmin
23+
group: 9869 # oneadmin
24+
mode: u=rwx,g=rx,o=
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
- name: Convert datastore directories into symlinks
3+
ansible.builtin.shell:
4+
cmd: |
5+
set -o errexit
6+
7+
if [[ -L '{{ _base_path }}' ]]; then
8+
exit 0
9+
fi
10+
11+
if ! [[ -d '{{ _mount_path }}' ]]; then
12+
echo 'Symlink target {{ _mount_path }} does not exist or is not a directory.' >&2
13+
exit 1
14+
fi
15+
16+
if [[ -d '{{ _base_path }}' ]] && ! rmdir '{{ _base_path }}'; then
17+
exit 2
18+
fi
19+
20+
if ! ln -s '{{ _mount_path }}' '{{ _base_path }}'; then
21+
exit 3
22+
fi
23+
24+
exit 78 # EREMCHG
25+
executable: /bin/bash
26+
when:
27+
- inventory_hostname in _hosts
28+
- ds_dict[item].id is defined
29+
# NOTE: It doesn't really make sense to symlink /var/lib/one/datastores/,
30+
# so we use that as a skip condition.
31+
- _mount_path != '/var/lib/one/datastores'
32+
vars:
33+
# This isn't strictly a "mountpoint".
34+
_mount_path: >-
35+
{{ ds_dict[item].symlink.src | d('/var/lib/one/datastores/') | normpath }}
36+
_base_path: >-
37+
/var/lib/one/datastores/{{ ds_dict[item].id }}
38+
_hosts: >-
39+
{{ ds_dict[item].symlink.groups | d([])
40+
| map('extract', groups)
41+
| flatten
42+
| unique }}
43+
register: shell
44+
changed_when:
45+
- shell.rc in [78]
46+
failed_when:
47+
- shell.rc not in [0, 78]
48+
loop: "{{ ds_names }}"

roles/datastore/generic/tasks/common.yml

Lines changed: 0 additions & 78 deletions
This file was deleted.
Lines changed: 40 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
---
22
- ansible.builtin.import_tasks:
3-
file: "{{ role_path }}/tasks/common.yml"
4-
vars:
5-
common_task: init
3+
file: "{{ role_path }}/tasks/_init.yml"
64

75
- ansible.builtin.include_role:
86
name: opennebula/leader
97
when: leader is undefined
108

11-
- when: inventory_hostname == leader
9+
- delegate_to: "{{ leader }}"
10+
run_once: true
1211
block:
1312
- name: Get Datastores
1413
ansible.builtin.shell:
@@ -17,22 +16,20 @@
1716
changed_when: false
1817
register: shell
1918

20-
- name: Parse Datastores
21-
ansible.builtin.set_fact:
22-
ds_names_parsed: >-
23-
{{ _names }}
24-
ds_dict_parsed: >-
25-
{{ dict(_names | zip(_datastores)) }}
26-
vars:
27-
_document: >-
28-
{{ shell.stdout | from_json }}
29-
_datastores: >-
30-
{{ [_document.DATASTORE_POOL.DATASTORE | d([])] | flatten }}
31-
_names: >-
32-
{{ _datastores | map(attribute='NAME') | d([]) | list }}
19+
- name: Parse Datastores
20+
ansible.builtin.set_fact:
21+
ds_names_parsed: >-
22+
{{ _names }}
23+
ds_dict_parsed: >-
24+
{{ dict(_names | zip(_datastores)) }}
25+
vars:
26+
_document: >-
27+
{{ shell.stdout | from_json }}
28+
_datastores: >-
29+
{{ [_document.DATASTORE_POOL.DATASTORE | d([])] | flatten }}
30+
_names: >-
31+
{{ _datastores | map(attribute='NAME') | d([]) | list }}
3332
34-
- when: inventory_hostname == leader
35-
block:
3633
# NOTE: Only "system" datastores can be enabled or disabled.
3734
- name: Update Datastores
3835
ansible.builtin.shell:
@@ -51,9 +48,11 @@
5148
{{ _combined | opennebula.deploy.to_one }}
5249
executable: /bin/bash
5350
changed_when: true
54-
when: (_combined | opennebula.deploy.to_one != ds_dict_parsed[item].TEMPLATE | opennebula.deploy.to_one)
55-
or
56-
(ds_dict[item].enabled is defined and (ds_dict[item].enabled != (ds_dict_parsed[item].STATE | int == 0)))
51+
when:
52+
- ds_dict[item].id is defined
53+
- (_combined | opennebula.deploy.to_one != ds_dict_parsed[item].TEMPLATE | opennebula.deploy.to_one)
54+
or
55+
(ds_dict[item].enabled is defined and (ds_dict[item].enabled != (ds_dict_parsed[item].STATE | int == 0)))
5756
loop: "{{ _existing }}"
5857
vars:
5958
_existing: >-
@@ -75,37 +74,29 @@
7574
executable: /bin/bash
7675
changed_when: true
7776
loop: "{{ _missing }}"
78-
register: new_ds
77+
register: shell_create_datastores
7978
vars:
8079
_missing: >-
8180
{{ ds_names | reject('in', ds_names_parsed) }}
8281
83-
- name: Map created datastores
82+
- name: Merge back datastore IDs into ds_dict
8483
ansible.builtin.set_fact:
85-
ds_map: >-
86-
{{ (ds_map | default({})) | combine({
87-
(item.item): {
88-
'id': (item.stdout.splitlines()[-1].split(':')[-1] | trim),
89-
'src': ds_dict[item.item].symlink.src | default('/var/lib/one/datastores/') | normpath,
90-
'groups': ds_dict[item.item].symlink.groups | default([])
91-
}
92-
}) }}
93-
loop: "{{ new_ds.results | default([]) }}"
94-
loop_control:
95-
label: "{{ item.item }}"
96-
run_once: true
97-
when: new_ds is defined
98-
99-
- name: Publish datastore mapping
100-
ansible.builtin.add_host:
101-
name: datastore_mapping_host
102-
groups: datastore_map
103-
ds_map: "{{ hostvars[inventory_hostname].ds_map | default({}) }}"
104-
run_once: true
105-
when:
106-
- hostvars[inventory_hostname].ds_map is defined
84+
ds_dict: >-
85+
{{ ds_dict | combine(_update1, _update2, recursive=true) }}
86+
vars:
87+
# IDs can be sourced either from initial parse or immediately after new datastores are created.
88+
_update1: >-
89+
{%- set output = [] -%}
90+
{%- for item in ds_dict_parsed.items() -%}
91+
{{- output.append([item.0, {"id": item.1.ID | int}]) -}}
92+
{%- endfor -%}
93+
{{- dict(output) -}}
94+
_update2: >-
95+
{%- set output = [] -%}
96+
{%- for item in shell_create_datastores.results -%}
97+
{{- output.append([item.item, {"id": item.stdout_lines[-1].split(':')[-1] | trim | int}]) -}}
98+
{%- endfor -%}
99+
{{- dict(output) -}}
107100
108101
- ansible.builtin.import_tasks:
109-
file: "{{ role_path }}/tasks/common.yml"
110-
vars:
111-
common_task: symlink
102+
file: "{{ role_path }}/tasks/_link.yml"
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
- ansible.builtin.import_tasks:
3-
file: "{{ role_path }}/tasks/common.yml"
4-
vars:
5-
common_task: all
3+
file: "{{ role_path }}/tasks/_init.yml"
4+
5+
- ansible.builtin.import_tasks:
6+
file: "{{ role_path }}/tasks/_link.yml"

0 commit comments

Comments
 (0)