This is an automated email from the ASF dual-hosted git repository.

ssulav pushed a commit to branch HDDS-14679
in repository https://gitbox.apache.org/repos/asf/ozone-installer.git


The following commit(s) were added to refs/heads/HDDS-14679 by this push:
     new da07ed3  HDDS-14679. Separate out data and metadata base path
da07ed3 is described below

commit da07ed30642ef1eb0c08e6d74921f3b67c101a85
Author: Soumitra Sulav <[email protected]>
AuthorDate: Fri Feb 20 16:24:02 2026 +0530

    HDDS-14679. Separate out data and metadata base path
---
 README.md                                      |  6 ++++--
 ozone_installer.py                             | 15 +++++++++++----
 playbooks/cluster.yml                          |  4 ++++
 playbooks/stop_and_clean.yml                   |  4 ++++
 roles/ozone_cleanup/tasks/main.yml             |  4 ++--
 roles/ozone_config/templates/ozone-site.xml.j2 | 15 ++++++++-------
 roles/ozone_layout/tasks/main.yml              |  9 +++++++--
 7 files changed, 40 insertions(+), 17 deletions(-)

diff --git a/README.md b/README.md
index 07ef806..64ecb0c 100644
--- a/README.md
+++ b/README.md
@@ -270,7 +270,8 @@ 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`). 
Supports comma-separated multiple directories (e.g. 
`/data/ozone1,/data/ozone2`) or brace expansion (e.g. `/data/ozone{1..3}` → 
`/data/ozone1,/data/ozone2,/data/ozone3`); each path gets `dn`, `meta`, 
`data/om`, etc. subdirs in `ozone-site.xml`.
+- Data base (`data_base`, `-dd`/`--data-dir`, default `/data/ozone`): Datanode 
block storage; maps to `hdds.datanode.dir`. Supports comma-separated multiple 
directories (e.g. `/data/ozone1,/data/ozone2`) or brace expansion (e.g. 
`/data/ozone{1..3}`); each path gets a `dn` subdir.
+- Metadata base (`metadata_base`, `-md`/`--metadata-dir`, default: same as 
`data_base`): Metadata storage for `ozone.metadata.dirs`, `ozone.om.db.dirs`, 
`ozone.scm.db.dirs`, etc. Supports comma-separated dirs or brace expansion; 
each path gets `meta`, `data/om`, `data/scm`, etc. subdirs.
 
 ## Components and config mapping
 
@@ -279,7 +280,8 @@ ANSIBLE_CONFIG=ansible.cfg ansible-playbook -i 
inventories/dev/hosts.ini playboo
   - **Legacy mode** (`-H`/`-F`): Non‑HA: first host runs OM+SCM+Recon; all 
hosts are DNs. 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` (comma-separated dirs are expanded per property)
+  - `hdds.datanode.dir` maps to `data_base` (comma-separated dirs expanded per 
path)
+  - `ozone.metadata.dirs`, `ozone.om.db.dirs`, `ozone.scm.db.dirs`, and 
related paths map to `metadata_base` (defaults to `data_base` when not 
specified)
   - 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 15b9ef5..f512e6f 100755
--- a/ozone_installer.py
+++ b/ozone_installer.py
@@ -95,7 +95,8 @@ 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(s), comma-separated or 
brace expansion e.g. /data/ozone{{1..3}} (default: {DEFAULTS['data_base']})")
+    p.add_argument("-dd", "--data-dir", help=f"Datanode block storage dir(s), 
maps to hdds.datanode.dir; comma-separated or brace expansion e.g. 
/data/ozone{{1..3}} (default: {DEFAULTS['data_base']})")
+    p.add_argument("-md", "--metadata-dir", help=f"Metadata dir(s) for 
ozone.metadata.dirs, ozone.om.db.dirs, etc.; comma-separated or brace expansion 
(default: same as --data-dir)")
     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)")
@@ -602,8 +603,10 @@ 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 to remove", 
default=DEFAULTS["install_base"], yes_mode=yes)
         data_base_raw = args.data_dir or (last_cfg.get("data_base") if 
last_cfg else None) or prompt("Data directory to remove", 
default=DEFAULTS["data_base"], yes_mode=yes)
         data_base = parse_data_dirs(data_base_raw) if data_base_raw else 
(data_base_raw or DEFAULTS["data_base"])
+        metadata_base_raw = getattr(args, "metadata_dir", None) or 
(last_cfg.get("metadata_base") if last_cfg else None) or data_base
+        metadata_base = parse_data_dirs(metadata_base_raw) if 
metadata_base_raw else (metadata_base_raw or data_base)
         playbook = PLAYBOOKS_DIR / "stop_and_clean.yml"
-        extra_vars = {"cluster_mode": cluster_mode, "ssh_user": ssh_user, 
"install_base": install_base, "data_base": data_base, "controller_logs_dir": 
str(LOGS_DIR)}
+        extra_vars = {"cluster_mode": cluster_mode, "ssh_user": ssh_user, 
"install_base": install_base, "data_base": data_base, "metadata_base": 
metadata_base, "controller_logs_dir": str(LOGS_DIR)}
         logger.info("Running stop and clean on cluster...")
     else:
         # Full install: resolve version, paths, service config, etc.
@@ -631,8 +634,10 @@ 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_raw = args.data_dir or (last_cfg.get("data_base") if 
last_cfg else None) \
-            or prompt("Data directory (base path(s), comma-separated or brace 
expansion e.g. /data/ozone{1..3})", default=DEFAULTS["data_base"], yes_mode=yes)
+            or prompt("Data directory (hdds.datanode.dir; base path(s), 
comma-separated or brace expansion e.g. /data/ozone{1..3})", 
default=DEFAULTS["data_base"], yes_mode=yes)
         data_base = parse_data_dirs(data_base_raw) if data_base_raw else 
(data_base_raw or DEFAULTS["data_base"])
+        metadata_base_raw = getattr(args, "metadata_dir", None) or 
(last_cfg.get("metadata_base") if last_cfg else None) or data_base
+        metadata_base = parse_data_dirs(metadata_base_raw) if 
metadata_base_raw else (metadata_base_raw or data_base)
 
         service_user = args.service_user or (last_cfg.get("service_user") if 
last_cfg else None) \
             or prompt("Service user name ", default=DEFAULTS["service_user"], 
yes_mode=yes)
@@ -694,7 +699,8 @@ def main(argv: List[str]) -> int:
             ("Ozone version", str(ozone_version)),
             ("JDK major", str(jdk_major)),
             ("Install directory", str(install_base)),
-            ("Data directory", str(data_base)),
+            ("Data directory (hdds.datanode.dir)", str(data_base)),
+            ("Metadata directory (ozone.metadata.dirs, etc.)", 
str(metadata_base)),
             ("SSH user", str(ssh_user)),
             ("SSH auth method", str(auth_method))
         ]
@@ -730,6 +736,7 @@ def main(argv: List[str]) -> int:
             "cluster_mode": cluster_mode,
             "install_base": install_base,
             "data_base": data_base,
+            "metadata_base": metadata_base,
             "jdk_major": jdk_major,
             "service_user": service_user,
             "service_group": service_group,
diff --git a/playbooks/cluster.yml b/playbooks/cluster.yml
index fd0389c..1420f1b 100644
--- a/playbooks/cluster.yml
+++ b/playbooks/cluster.yml
@@ -28,6 +28,10 @@
       set_fact:
         data_base_list: "{{ ((data_base | default('')).split(',') | 
map('trim') | select | list) | default([data_base | default('/data/ozone')], 
true) }}"
 
+    - name: "Pre-install: Parse metadata_base into list (supports 
comma-separated dirs)"
+      set_fact:
+        metadata_base_list: "{{ ((metadata_base | default(data_base) | 
default('')).split(',') | map('trim') | select | list) | default([metadata_base 
| default(data_base) | default('/data/ozone')], true) }}"
+
     - name: "Pre-install: Gather facts"
       setup:
 
diff --git a/playbooks/stop_and_clean.yml b/playbooks/stop_and_clean.yml
index 2c77a6a..1920614 100644
--- a/playbooks/stop_and_clean.yml
+++ b/playbooks/stop_and_clean.yml
@@ -22,6 +22,10 @@
       set_fact:
         data_base_list: "{{ ((data_base | default('')).split(',') | 
map('trim') | select | list) | default([data_base | default('/data/ozone')], 
true) }}"
 
+    - name: "Parse metadata_base into list"
+      set_fact:
+        metadata_base_list: "{{ ((metadata_base | default(data_base) | 
default('')).split(',') | map('trim') | select | list) | default([metadata_base 
| default(data_base) | default('/data/ozone')], true) }}"
+
     - name: "Gather facts"
       setup:
 
diff --git a/roles/ozone_cleanup/tasks/main.yml 
b/roles/ozone_cleanup/tasks/main.yml
index 9a0095e..c190ac7 100644
--- a/roles/ozone_cleanup/tasks/main.yml
+++ b/roles/ozone_cleanup/tasks/main.yml
@@ -39,11 +39,11 @@
         state: absent
       become: true
 
-    - name: "Remove data directories"
+    - name: "Remove data and metadata directories"
       file:
         path: "{{ item }}"
         state: absent
-      loop: "{{ data_base_list | default([data_base | default('/data/ozone')]) 
}}"
+      loop: "{{ ((data_base_list | default([data_base | 
default('/data/ozone')])) + (metadata_base_list | default([metadata_base | 
default(data_base) | default('/data/ozone')]))) | unique }}"
       become: true
 
 
diff --git a/roles/ozone_config/templates/ozone-site.xml.j2 
b/roles/ozone_config/templates/ozone-site.xml.j2
index db8d458..3b8b967 100644
--- a/roles/ozone_config/templates/ozone-site.xml.j2
+++ b/roles/ozone_config/templates/ozone-site.xml.j2
@@ -17,7 +17,8 @@
 <configuration>
   <!-- Minimal Ozone site config; extend via group_vars if needed -->
 {% set _data_bases = data_base_list | default([data_base | 
default('/data/ozone')]) %}
-{% set _first_disk = _data_bases | first %}
+{% set _metadata_bases = metadata_base_list | default([metadata_base | 
default(data_base) | default('/data/ozone')]) %}
+{% set _first_metadata = _metadata_bases | first %}
 {% set _om_all = groups.get('om', [])| list %}
 {% set _scm_all = groups.get('scm', []) | list %}
 {% set _all_dn_count = groups.get('datanodes', []) | list | length %}
@@ -103,7 +104,7 @@
 {% endif %}
   <property>
     <name>ozone.metadata.dirs</name>
-    <value>{{ _first_disk }}/meta</value>
+    <value>{{ _first_metadata }}/meta</value>
   </property>
   <property>
     <name>hdds.datanode.dir</name>
@@ -111,23 +112,23 @@
   </property>
   <property>
     <name>dfs.container.ratis.datanode.storage.dir</name>
-    <value>{{ _first_disk }}/meta/dn</value>
+    <value>{{ _first_metadata }}/meta/dn</value>
   </property>
   <property>
     <name>ozone.om.db.dirs</name>
-    <value>{{ _first_disk }}/data/om</value>
+    <value>{{ _first_metadata }}/data/om</value>
   </property>
   <property>
     <name>ozone.om.ratis.snapshot.dir</name>
-    <value>{{ _first_disk }}/meta/om</value>
+    <value>{{ _first_metadata }}/meta/om</value>
   </property>
   <property>
     <name>ozone.scm.db.dirs</name>
-    <value>{{ _first_disk }}/data/scm</value>
+    <value>{{ _first_metadata }}/data/scm</value>
   </property>
   <property>
     <name>ozone.scm.datanode.id.dir</name>
-    <value>{{ _first_disk }}/meta/scm</value>
+    <value>{{ _first_metadata }}/meta/scm</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 43c5c44..4ca880c 100644
--- a/roles/ozone_layout/tasks/main.yml
+++ b/roles/ozone_layout/tasks/main.yml
@@ -14,14 +14,19 @@
 # limitations under the License.
 
 ---
-- name: "Create install and data directories"
+- name: "Create install, data (hdds.datanode.dir) and metadata directories"
   file:
     path: "{{ item }}"
     state: directory
     owner: "{{ service_user }}"
     group: "{{ service_group }}"
     mode: "0755"
-  loop: "{{ [install_base] + (data_base_list | default([data_base | 
default('/data/ozone')]) | product(['', '/dn', '/meta']) | map('join', '') | 
list) }}"
+  loop: >-
+    {{
+      [install_base]
+      + (data_base_list | default([data_base | default('/data/ozone')]) | 
map('regex_replace', '$', '/dn') | list)
+      + (metadata_base_list | default([metadata_base | default(data_base) | 
default('/data/ozone')]) | product(['/meta', '/meta/dn', '/data/om', 
'/meta/om', '/data/scm', '/meta/scm']) | map('join') | list)
+    }}
   become: true
 
 - name: "Ensure OZONE_HOME and PATH are in profile.d/ozone.sh"


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to