This is an automated email from the ASF dual-hosted git repository. ssulav pushed a commit to branch HDDS-14667 in repository https://gitbox.apache.org/repos/asf/ozone-installer.git
commit e6134e438c018b8905a2ab76711c963de37b3942 Author: Soumitra Sulav <[email protected]> AuthorDate: Thu Feb 19 22:01:42 2026 +0530 HDDS-14667. Add support for multiple disks ozone installation --- README.md | 4 ++-- ozone_installer.py | 4 ++-- playbooks/cluster.yml | 5 +++++ roles/cleanup/tasks/main.yml | 5 +++-- roles/ozone_config/defaults/main.yml | 1 + roles/ozone_config/templates/ozone-site.xml.j2 | 15 ++++++++------- roles/ozone_layout/tasks/main.yml | 6 +----- roles/ozone_service/tasks/main.yml | 4 ++-- 8 files changed, 24 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 6a3e710..14447a2 100644 --- a/README.md +++ b/README.md @@ -256,7 +256,7 @@ ANSIBLE_CONFIG=ansible.cfg ansible-playbook -i inventories/dev/hosts.ini playboo ### Directories - Install base (`install_base`, default `/opt/ozone`): where Ozone binaries and configs live. A `current` symlink points to the active version directory. -- Data base (`data_base`, default `/data/ozone`): where Ozone writes on‑disk metadata and Datanode data (e.g., `ozone.metadata.dirs`, `hdds.datanode.dir`). +- Data base (`data_base`, default `/data/ozone`): where Ozone writes on‑disk metadata and Datanode data (e.g., `ozone.metadata.dirs`, `hdds.datanode.dir`). Supports comma-separated multiple directories (e.g. `/data/ozone1,/data/ozone2`); each path gets `dn`, `meta`, `data/om`, etc. subdirs in `ozone-site.xml`. ## Components and config mapping @@ -265,7 +265,7 @@ ANSIBLE_CONFIG=ansible.cfg ansible-playbook -i inventories/dev/hosts.ini playboo - HA: first three hosts serve as OM and SCM sets; all hosts are DNs; first host is Recon. - `ozone-site.xml` is rendered from templates based on inventory groups: - `ozone.scm.names`, `ozone.scm.client.address`, `ozone.om.address` or HA service IDs - - `ozone.metadata.dirs`, `hdds.datanode.dir`, and related paths map to `data_base` + - `ozone.metadata.dirs`, `hdds.datanode.dir`, and related paths map to `data_base` (comma-separated dirs are expanded per property) - Replication is set to ONE if DN count < 3, otherwise THREE ## Optional: S3 Gateway (S3G) and smoke diff --git a/ozone_installer.py b/ozone_installer.py index 93c0084..eb1401f 100755 --- a/ozone_installer.py +++ b/ozone_installer.py @@ -85,7 +85,7 @@ def parse_args(argv: List[str]) -> argparse.Namespace: p.add_argument("-k", "--keyfile", help="SSH private key file (for --auth-method=key)") p.add_argument("-v", "--version", help="Ozone version (e.g., 2.0.0) or 'local'") p.add_argument("-i", "--install-dir", help=f"Install root (default: {DEFAULTS['install_base']})") - p.add_argument("-d", "--data-dir", help=f"Data root (default: {DEFAULTS['data_base']})") + p.add_argument("-d", "--data-dir", help=f"Data root(s), comma-separated for multiple (default: {DEFAULTS['data_base']})") p.add_argument("-s", "--start", action="store_true", help="Initialize and start after install") p.add_argument("-M", "--cluster-mode", choices=["non-ha", "ha"], help="Force cluster mode (default: auto by host count)") p.add_argument("-r", "--role-file", help="Role file (YAML) for HA mapping (optional)") @@ -501,7 +501,7 @@ def main(argv: List[str]) -> int: install_base = args.install_dir or (last_cfg.get("install_base") if last_cfg else None) \ or prompt("Install directory (base directory path to store ozone binaries, configs and logs)", default=DEFAULTS["install_base"], yes_mode=yes) data_base = args.data_dir or (last_cfg.get("data_base") if last_cfg else None) \ - or prompt("Data directory (base directory path to store ozone metadata and data)", default=DEFAULTS["data_base"], yes_mode=yes) + or prompt("Data directory (base path(s), comma-separated for multiple dirs)", default=DEFAULTS["data_base"], yes_mode=yes) # Auth (before service user/group) auth_method = args.auth_method or (last_cfg.get("auth_method") if last_cfg else None) \ diff --git a/playbooks/cluster.yml b/playbooks/cluster.yml index bef59f4..f67c45e 100644 --- a/playbooks/cluster.yml +++ b/playbooks/cluster.yml @@ -21,8 +21,13 @@ # Expect cluster_mode to be passed in (non-ha | ha). Fallback to non-ha. cluster_mode: "{{ cluster_mode | default('non-ha') }}" ha_enabled: "{{ cluster_mode == 'ha' }}" + # data_base_list: comma-separated data_base expanded to list (set in pre_tasks) pre_tasks: + - name: "Pre-install: Parse data_base into list (supports comma-separated dirs)" + set_fact: + data_base_list: "{{ ((data_base | default('')).split(',') | map('trim') | select | list) | default([data_base | default('/data/ozone')], true) }}" + - name: "Pre-install: Gather facts" setup: diff --git a/roles/cleanup/tasks/main.yml b/roles/cleanup/tasks/main.yml index 5d41c8f..14eb003 100644 --- a/roles/cleanup/tasks/main.yml +++ b/roles/cleanup/tasks/main.yml @@ -58,10 +58,11 @@ state: absent become: true - - name: "Remove data directory" + - name: "Remove data directories" file: - path: "{{ data_base }}" + path: "{{ item }}" state: absent + loop: "{{ data_base_list | default([data_base | default('/data/ozone')]) }}" become: true diff --git a/roles/ozone_config/defaults/main.yml b/roles/ozone_config/defaults/main.yml index 7473b5b..a527b6b 100644 --- a/roles/ozone_config/defaults/main.yml +++ b/roles/ozone_config/defaults/main.yml @@ -15,6 +15,7 @@ --- install_base: "/opt/ozone" +# data_base: single path or comma-separated paths (e.g. /data/ozone or /data/ozone1,/data/ozone2) data_base: "/data/ozone" CONFIG_DIR: "" # if provided, can be used to feed additional properties via vars diff --git a/roles/ozone_config/templates/ozone-site.xml.j2 b/roles/ozone_config/templates/ozone-site.xml.j2 index f838f03..f636c26 100644 --- a/roles/ozone_config/templates/ozone-site.xml.j2 +++ b/roles/ozone_config/templates/ozone-site.xml.j2 @@ -16,6 +16,7 @@ --> <configuration> <!-- Minimal Ozone site config; extend via group_vars if needed --> +{% set _data_bases = data_base_list | default([data_base | default('/data/ozone')]) %} {% set _om_all = groups.get('om', [])| list %} {% set _scm_all = groups.get('scm', []) | list %} {% set _all_dn_count = groups.get('datanodes', []) | list | length %} @@ -101,31 +102,31 @@ {% endif %} <property> <name>ozone.metadata.dirs</name> - <value>{{ data_base }}/meta</value> + <value>{% for d in _data_bases %}{{ d }}/meta{% if not loop.last %},{% endif %}{% endfor %}</value> </property> <property> <name>hdds.datanode.dir</name> - <value>{{ data_base }}/dn</value> + <value>{% for d in _data_bases %}{{ d }}/dn{% if not loop.last %},{% endif %}{% endfor %}</value> </property> <property> <name>dfs.container.ratis.datanode.storage.dir</name> - <value>{{ data_base }}/meta/dn</value> + <value>{% for d in _data_bases %}{{ d }}/meta/dn{% if not loop.last %},{% endif %}{% endfor %}</value> </property> <property> <name>ozone.om.db.dirs</name> - <value>{{ data_base }}/data/om</value> + <value>{% for d in _data_bases %}{{ d }}/data/om{% if not loop.last %},{% endif %}{% endfor %}</value> </property> <property> <name>ozone.om.ratis.snapshot.dir</name> - <value>{{ data_base }}/meta/om</value> + <value>{% for d in _data_bases %}{{ d }}/meta/om{% if not loop.last %},{% endif %}{% endfor %}</value> </property> <property> <name>ozone.scm.db.dirs</name> - <value>{{ data_base }}/data/scm</value> + <value>{% for d in _data_bases %}{{ d }}/data/scm{% if not loop.last %},{% endif %}{% endfor %}</value> </property> <property> <name>ozone.scm.datanode.id.dir</name> - <value>{{ data_base }}/meta/scm</value> + <value>{% for d in _data_bases %}{{ d }}/meta/scm{% if not loop.last %},{% endif %}{% endfor %}</value> </property> <property> <name>ozone.scm.skip.bootstrap.validation</name> diff --git a/roles/ozone_layout/tasks/main.yml b/roles/ozone_layout/tasks/main.yml index 5a5f0d8..43981fb 100644 --- a/roles/ozone_layout/tasks/main.yml +++ b/roles/ozone_layout/tasks/main.yml @@ -21,11 +21,7 @@ owner: "{{ service_user }}" group: "{{ service_group }}" mode: "0755" - loop: - - "{{ install_base }}" - - "{{ data_base }}" - - "{{ data_base }}/dn" - - "{{ data_base }}/meta" + loop: "{{ [install_base] + [d ~ sub for d in (data_base_list | default([data_base | default('/data/ozone')])) for sub in ['', '/dn', '/meta']] }}" become: true - name: "Ensure OZONE_HOME and PATH are in profile.d/ozone.sh" diff --git a/roles/ozone_service/tasks/main.yml b/roles/ozone_service/tasks/main.yml index b4ce240..8746028 100644 --- a/roles/ozone_service/tasks/main.yml +++ b/roles/ozone_service/tasks/main.yml @@ -27,7 +27,7 @@ - name: "Initialize first SCM" command: "ozone scm --init" args: - creates: "{{ data_base }}/meta/scm" + creates: "{{ (data_base_list | first) | default(data_base) }}/meta/scm" when: (groups['scm'] | length > 0) and (inventory_hostname == groups['scm'][0]) register: scm_init_first failed_when: scm_init_first.rc != 0 @@ -41,7 +41,7 @@ - name: "Initialize first OM" command: "ozone om --init" args: - creates: "{{ data_base }}/meta/om" + creates: "{{ (data_base_list | first) | default(data_base) }}/meta/om" when: (groups['om'] | length > 0) and (inventory_hostname == groups['om'][0]) register: om_init_first failed_when: om_init_first.rc != 0 --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
