Skip to content

Commit 0a01b47

Browse files
katarimanojkevallesp
authored andcommitted
Add IPv6 external Ceph support with gathering parameter
This patch adds support for deploying external Ceph in IPv6 environment and introduces a new 'gathering' parameter for hook playbooks to control Ansible fact gathering behavior. Changes: - Add run_hook 'gathering' parameter to set ANSIBLE_GATHERING env var This allows hooks to force fresh fact gathering (implicit) instead of using cached facts (smart), fixing issues where network interfaces are configured after initial fact gathering - Add setup_cephnodes_ipv6.yaml hook playbook to prepare Ceph nodes for IPv6 deployment (repo setup, CA configuration, network setup) - Add create_external_ceph_params.yml hook playbook and create_external_ceph_params.sh script to generate external Ceph parameters tht file from deployed Ceph cluster and copy configuration files to controller node - Update run_hook README with documentation for gathering parameter The gathering parameter is particularly useful when network interfaces are configured during playbook execution and fresh facts are needed to capture all IPv6 addresses.
1 parent f66a47b commit 0a01b47

File tree

5 files changed

+224
-6
lines changed

5 files changed

+224
-6
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
# This Playbook runs the shell script that extracts Ceph credentials to create the tht parameter file and copy required ceph conf files on osp-controller
3+
4+
- name: Create external Ceph parameters file and copy ceph client conf files
5+
hosts: localhost
6+
gather_facts: false
7+
8+
tasks:
9+
- name: Execute external Ceph parameters creation script
10+
ansible.builtin.script: "{{ playbook_dir }}/../../scripts/create_external_ceph_params.sh {{ ceph_node }} {{ ceph_mon_host }}"
11+
register: script_output
12+
13+
- name: Display script output
14+
ansible.builtin.debug:
15+
var: script_output.stdout_lines
16+
17+
- name: Display script errors if any
18+
when: script_output.stderr_lines | length > 0
19+
ansible.builtin.debug:
20+
msg: "Script stderr: {{ script_output.stderr_lines }}"
21+
22+
- name: Verify external_ceph_params.yaml was created
23+
delegate_to: osp-undercloud-0
24+
ansible.builtin.stat:
25+
path: "{{ ansible_user_dir }}/external_ceph_params.yaml"
26+
register: params_file_stat
27+
28+
- name: Confirm file creation
29+
ansible.builtin.debug:
30+
msg: "Successfully created external_ceph_params.yaml on osp-undercloud-0"
31+
when: params_file_stat.stat.exists
32+
33+
- name: Fail if file wasn't created
34+
ansible.builtin.fail:
35+
msg: "Failed to create external_ceph_params.yaml on osp-undercloud-0"
36+
when: not params_file_stat.stat.exists
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
---
2+
- name: Setup repos, CA and networks on ceph nodes
3+
hosts: "{{ cifmw_ceph_target | default('ceph') }}"
4+
gather_facts: true
5+
become: true
6+
vars:
7+
cifmw_adoption_osp_deploy_ntp_server: "pool.ntp.org"
8+
cifmw_adoption_osp_deploy_repos:
9+
- rhel-9-for-x86_64-baseos-eus-rpms
10+
- rhel-9-for-x86_64-appstream-eus-rpms
11+
- rhel-9-for-x86_64-highavailability-eus-rpms
12+
- openstack-17.1-for-rhel-9-x86_64-rpms
13+
- fast-datapath-for-rhel-9-x86_64-rpms
14+
- rhceph-7-tools-for-rhel-9-x86_64-rpms
15+
common_dns: ["2620:cf:cf:aaaa::1"]
16+
base_config: "/etc/os-net-config"
17+
tasks:
18+
- name: Setup repositories via rhos-release if needed
19+
ansible.builtin.import_role:
20+
name: repo_setup
21+
tasks_from: rhos_release.yml
22+
23+
- name: Install custom CA if needed
24+
ansible.builtin.import_role:
25+
name: install_ca
26+
- name: Ensure needed logins
27+
ansible.builtin.import_role:
28+
name: adoption_osp_deploy
29+
tasks_from: login_registries.yml
30+
31+
- name: Ensure repos are setup
32+
become: true
33+
community.general.rhsm_repository:
34+
name: "{{ cifmw_adoption_osp_deploy_repos }}"
35+
state: enabled
36+
37+
- name: Ensure os-net-config folder exists in ceph nodes
38+
become: true
39+
ansible.builtin.file:
40+
path: "/etc/os-net-config"
41+
state: directory
42+
mode: '0755'
43+
44+
- name: Ensure os-net-config and openvswitch is installed in ceph nodes
45+
become: true
46+
ansible.builtin.dnf:
47+
name:
48+
- os-net-config
49+
- openvswitch
50+
state: present
51+
52+
- name: Generate os-net-config YAML
53+
ansible.builtin.copy:
54+
dest: "{{ base_config }}/network-os-net-config.yaml"
55+
mode: '0644'
56+
content: |
57+
network_config:
58+
- type: ovs_bridge
59+
name: br-ex
60+
mtu: 1500
61+
use_dhcp: false
62+
dns_servers: {{ common_dns }}
63+
addresses:
64+
- ip_netmask: "{{ hostvars[inventory_hostname]['bridge_ip'] }}"
65+
routes: []
66+
members:
67+
- type: interface
68+
name: nic2
69+
mtu: 1500
70+
primary: true
71+
addresses:
72+
- ip_netmask: "{{ hostvars[inventory_hostname]['external_ip'] }}"
73+
routes: []
74+
- type: vlan
75+
vlan_id: 20
76+
addresses:
77+
- ip_netmask: "{{ hostvars[inventory_hostname]['internalapi_ip'] }}"
78+
routes: []
79+
- type: vlan
80+
vlan_id: 21
81+
addresses:
82+
- ip_netmask: "{{ hostvars[inventory_hostname]['storage_ip'] }}"
83+
routes: []
84+
- type: vlan
85+
vlan_id: 23
86+
addresses:
87+
- ip_netmask: "{{ hostvars[inventory_hostname]['storagemgmt_ip'] }}"
88+
routes: []
89+
- type: vlan
90+
vlan_id: 22
91+
addresses:
92+
- ip_netmask: "{{ hostvars[inventory_hostname]['tenant_ip'] }}"
93+
routes: []
94+
95+
- name: Apply network configuration
96+
ansible.builtin.command: >
97+
os-net-config -c {{ base_config }}/network-os-net-config.yaml -v
98+
changed_when: true
99+
100+
- name: Set net.ipv6.ip_nonlocal_bind
101+
ansible.posix.sysctl:
102+
name: net.ipv6.ip_nonlocal_bind
103+
value: '1'
104+
state: present

roles/run_hook/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ name:
3737
* `source`: (String) Source of the playbook. If it's a filename, the playbook is expected in `hooks/playbooks`. It can be an absolute path.
3838
* `type`: (String) Type of the hook. In this case, set it to `playbook`.
3939
* `extra_vars`: (Dict) Structure listing the extra variables you would like to pass down ([extra_vars explained](#extra_vars-explained))
40+
* `gathering`: (String) Set the ANSIBLE_GATHERING environment variable. Valid values: `implicit`, `explicit`, `smart`. Defaults to empty string (uses ansible.cfg setting).
4041
* `hook_retry` (Boolean) Set true, if the hook execution should be retried on failure
4142

4243
##### About OpenShift namespaces and install_yamls
@@ -56,6 +57,7 @@ Since `install_yamls` might not be initialized, the `run_hook` is exposing two n
5657
* `source`: (String) Source of the playbook. If it's a filename, the playbook is expected in `hooks/playbooks`. It can be an absolute path.
5758
* `type`: (String) Type of the hook. In this case, set it to `playbook`.
5859
* `extra_vars`: (Dict) Structure listing the extra variables you would like to pass down ([extra_vars explained](#extra_vars-explained))
60+
* `gathering`: (String) Set the ANSIBLE_GATHERING environment variable. Valid values: `implicit`, `explicit`, `smart`. Defaults to empty string (uses ansible.cfg setting).
5961
* `hook_retry` (Boolean) Set true, if the hook execution should be retried on failure
6062

6163
#### Hook callback
@@ -133,6 +135,7 @@ pre_deploy:
133135
- name: My hook
134136
source: ceph-deploy.yml
135137
type: playbook
138+
gathering: implicit
136139
extra_vars:
137140
UUID: <some generated UUID>
138141
file: "ceph_env.yml"

roles/run_hook/tasks/playbook.yml

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,15 @@
9494
no_log: "{{ cifmw_nolog | default(true) | bool }}"
9595
cifmw.general.ci_script:
9696
output_dir: "{{ cifmw_basedir }}/artifacts"
97-
extra_args:
98-
ANSIBLE_CONFIG: "{{ hook.config_file | default(ansible_config_file) }}"
99-
ANSIBLE_LOG_PATH: "{{ log_path }}"
97+
extra_args: >-
98+
{{
99+
{
100+
'ANSIBLE_CONFIG': hook.config_file | default(ansible_config_file),
101+
'ANSIBLE_LOG_PATH': log_path
102+
} | combine(
103+
{'ANSIBLE_GATHERING': hook.gathering} if hook.gathering is defined else {}
104+
)
105+
}}
100106
creates: "{{ hook.creates | default(omit) }}"
101107
script: >-
102108
ansible-playbook -i {{ hook.inventory | default(inventory_file) }}
@@ -115,9 +121,15 @@
115121
no_log: "{{ cifmw_nolog | default(true) | bool }}"
116122
cifmw.general.ci_script:
117123
output_dir: "{{ cifmw_basedir }}/artifacts"
118-
extra_args:
119-
ANSIBLE_CONFIG: "{{ hook.config_file | default(ansible_config_file) }}"
120-
ANSIBLE_LOG_PATH: "{{ log_path }}"
124+
extra_args: >-
125+
{{
126+
{
127+
'ANSIBLE_CONFIG': hook.config_file | default(ansible_config_file),
128+
'ANSIBLE_LOG_PATH': log_path
129+
} | combine(
130+
{'ANSIBLE_GATHERING': hook.gathering} if hook.gathering is defined else {}
131+
)
132+
}}
121133
creates: "{{ hook.creates | default(omit) }}"
122134
script: >-
123135
ansible-playbook -i {{ hook.inventory | default(inventory_file) }}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/bin/bash
2+
# Create tht external_ceph_params.yaml on undercloud and update ceph_conf files in osp-controller
3+
4+
set -e # Exit on any error
5+
6+
# Parameters - only Ceph-specific values
7+
CEPH_NODE=${1}
8+
CEPH_MON_HOST=${2}
9+
10+
# Validate required parameters
11+
if [ -z "$CEPH_NODE" ] || [ -z "$CEPH_MON_HOST" ]; then
12+
echo "ERROR: Missing required parameters"
13+
echo "Usage: $0 <ceph_node> <ceph_mon_host>"
14+
echo " ceph_node: Name of the Ceph node (e.g., osp-ext-ceph-uni04delta-ipv6-0)"
15+
echo " ceph_mon_host: Comma-separated list of Ceph monitor IPs (e.g., 2620:cf:cf:cccc::6a,2620:cf:cf:cccc::6b,2620:cf:cf:cccc::6c)"
16+
exit 1
17+
fi
18+
19+
echo "Creating external Ceph parameters file..."
20+
echo "Using Ceph node: $CEPH_NODE"
21+
echo "Using Ceph monitor hosts: $CEPH_MON_HOST"
22+
23+
# Extract Ceph credentials
24+
echo "Fetching Ceph credentials from $CEPH_NODE..."
25+
CEPH_OUTPUT=$(ssh "$CEPH_NODE" cat /etc/ceph/ceph.conf /etc/ceph/ceph.client.openstack.keyring)
26+
27+
FSID=$(echo "$CEPH_OUTPUT" | awk '/fsid =/ {print $3}')
28+
KEY=$(echo "$CEPH_OUTPUT" | awk '/key =/ {print $3}' | tr -d '"')
29+
30+
if [ -z "$FSID" ] || [ -z "$KEY" ]; then
31+
echo "ERROR: Failed to extract FSID or KEY from Ceph configuration"
32+
exit 1
33+
fi
34+
35+
echo "Found FSID: $FSID"
36+
echo "Found Key: $KEY"
37+
38+
# Create the parameter file on undercloud
39+
echo "Creating ~/external_ceph_params.yaml on osp-undercloud-0..."
40+
ssh osp-undercloud-0 "cat > ~/external_ceph_params.yaml" <<EOC
41+
parameter_defaults:
42+
CephClusterFSID: '$FSID'
43+
CephClientKey: '$KEY'
44+
CephManilaClientKey: '$KEY'
45+
CephExternalMonHost: '$CEPH_MON_HOST'
46+
EOC
47+
48+
echo "Successfully created ~/external_ceph_params.yaml on osp-undercloud-0"
49+
echo ""
50+
echo "File contents:"
51+
ssh osp-undercloud-0 "cat ~/external_ceph_params.yaml"
52+
53+
# Below code copies the ceph admin keyring and conf files that are required for adoption pre-requisites
54+
55+
echo "Copying Ceph configuration files from $CEPH_NODE to osp-controller-0..."
56+
57+
echo "Creating directory on controller..."
58+
ssh osp-controller-0 mkdir -p $HOME/ceph_client
59+
60+
ssh "$CEPH_NODE" sudo cat /etc/ceph/ceph.conf | ssh osp-controller-0 "cat > $HOME/ceph_client/ceph.conf"
61+
ssh "$CEPH_NODE" sudo cat /etc/ceph/ceph.client.admin.keyring | ssh osp-controller-0 "cat > $HOME/ceph_client/ceph.client.admin.keyring"
62+
63+
echo " Done! Files copied to osp-controller-0:$HOME/ceph_client/"

0 commit comments

Comments
 (0)