Skip to content

Commit ee49023

Browse files
authored
Merge pull request #247 from mhkarimi1383/metadata-dir-seperation
♻️ Separating metadata dir and data dir
2 parents 53ae124 + 379b615 commit ee49023

File tree

11 files changed

+125
-65
lines changed

11 files changed

+125
-65
lines changed

deploy/helm/rawfile-localpv/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ Please follow the [install guide](https://github.com/openebs/rawfile-localpv/tre
7474
| node.internalGRPC.port | int | `4500` | Port Number used for internal communication gRPC server |
7575
| node.internalGRPC.workers | int | `10` | gRPC worker count used for internal communication |
7676
| node.kubeletPath | string | `"/var/lib/kubelet"` | Kubelet path (Set to `/var/lib/k0s/kubelet` for k0s) |
77+
| node.metadataDirPath | string | `"/var/local/openebs/rawfile/meta"` | Metadata dir path for rawfile volumes metadata and tasks store file |
7778
| node.metrics.enabled | bool | `false` | |
7879
| node.priorityClassName | string | `"system-node-critical"` | priorityClassName for node component since this part is critical for node `system-node-critical` is default |
7980
| node.resources | object | `{}` | Sets compute resources for node component |

deploy/helm/rawfile-localpv/templates/controller/statefulset.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ spec:
3232
value: "{{ .Values.provisionerName }}"
3333
- name: CSI_DRIVER__ENDPOINT
3434
value: unix:///csi/csi.sock
35-
- name: NODE_DATADIR
36-
value: "{{ .Values.node.dataDirPath }}"
3735
- name: CSI_DRIVER__NODE_ID
3836
valueFrom:
3937
fieldRef:

deploy/helm/rawfile-localpv/templates/node-plugin/daemonset.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ spec:
3535
hostPath:
3636
path: {{ .Values.node.dataDirPath }}
3737
type: DirectoryOrCreate
38+
- name: metadata-dir
39+
hostPath:
40+
path: {{ .Values.node.metadataDirPath }}
41+
type: DirectoryOrCreate
3842
- name: device
3943
hostPath:
4044
path: /dev
@@ -48,8 +52,6 @@ spec:
4852
env:
4953
- name: PROVISIONER_NAME
5054
value: "{{ .Values.provisionerName }}"
51-
- name: NODE_DATADIR
52-
value: "{{ .Values.node.dataDirPath }}"
5355
- name: CSI_DRIVER__ENDPOINT
5456
value: unix:///csi/csi.sock
5557
- name: CSI_DRIVER__NODE_ID
@@ -61,6 +63,8 @@ spec:
6163
value: {{ .Values.metrics.enabled | toString | quote }}
6264
- name: CSI_DRIVER__METRICS_PORT
6365
value: {{ .Values.metrics.port | toString | quote }}
66+
- name: CSI_DRIVER__METADATA_DIR
67+
value: {{ .Values.node.metadataDirPath }}
6468
- name: NAMESPACE
6569
value: {{ .Release.Namespace }}
6670
- name: LOG_LEVEL
@@ -120,6 +124,8 @@ spec:
120124
mountPropagation: "Bidirectional"
121125
- name: data-dir
122126
mountPath: /data
127+
- name: metadata-dir
128+
mountPath: {{ .Values.node.metadataDirPath }}
123129
- name: device
124130
mountPath: /dev
125131
resources:

deploy/helm/rawfile-localpv/values.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ node:
129129
# -- Data dir path for provisioner to be used by provisioner
130130
dataDirPath: /var/csi/rawfile
131131

132+
# -- Metadata dir path for rawfile volumes metadata and tasks store file
133+
metadataDirPath: /var/local/openebs/rawfile/meta
134+
132135
# -- Kubelet path (Set to `/var/lib/k0s/kubelet` for k0s)
133136
kubeletPath: /var/lib/kubelet
134137

rawfile/config/model.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
AnyUrl,
1313
BaseModel,
1414
ByteSize,
15+
DirectoryPath,
1516
StringConstraints,
1617
Field,
1718
model_validator,
@@ -36,6 +37,10 @@ class CSIDriverCmd(BaseModel):
3637
description="Listen ip for gRPC server (used for internal communication only)",
3738
default=None,
3839
)
40+
metadata_dir: DirectoryPath | None = Field(
41+
description="Directory to store Metadata files, required and should point to an existing path when running node plugin",
42+
default=None,
43+
)
3944
internal_port: int | None = Field(
4045
description="Listen port for gRPC server (used for internal communication only)",
4146
default=None,
@@ -69,13 +74,16 @@ class CSIDriverCmd(BaseModel):
6974
)
7075

7176
@model_validator(mode="after")
72-
def validate_internal_endpoint(
77+
def validate_node_plugin(
7378
self,
7479
):
75-
if self.plugin_type == "node" and not self.internal_ip:
76-
raise ValueError(
77-
"Internal Communication IP/PORT is required on node plugin"
78-
)
80+
if self.plugin_type == "node":
81+
if not self.internal_ip:
82+
raise ValueError(
83+
"Internal Communication IP/PORT is required on node plugin"
84+
)
85+
if not self.metadata_dir:
86+
raise ValueError("Metadata Dir is required when running node plugin")
7987
return self
8088

8189

@@ -123,15 +131,6 @@ def settings_customise_sources(
123131
namespace: str = Field(
124132
description="K8s Namespace of the driver",
125133
)
126-
node_datadir: str = Field(
127-
description="""
128-
Data Directory path of the driver,
129-
where raw files, their matadata and their lock files are getting stored
130-
131-
NOTE that this path is used only for task pods, For CSI driver itself `/data` is used
132-
meaning that this path has to be mounted to `/data` in the CSI driver pod
133-
""",
134-
)
135134
log_level: Annotated[
136135
Literal["TRACE", "DEBUG", "INFO", "SUCCESS", "WARNING", "ERROR", "CRITICAL"],
137136
StringConstraints(strip_whitespace=True, to_upper=True),

rawfile/internal_svc.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
snapshots_dir,
1010
patch_metadata,
1111
)
12-
from utils.remote import is_attached
1312
from utils.lock import VolLock
1413
from typing import Final
1514
from utils.storage_pool import get_capacity
15+
from utils.volume_manager import manager as volume_manager
1616
import grpc
1717

1818
SIGNATURE_METADATA: Final[str] = "x-signature"
@@ -54,13 +54,13 @@ def ExpandRawFile(
5454
size_inc = request.new_size - metadata(request.volume_id)["size"]
5555
if size_inc <= 0:
5656
return internal_pb2.ExpandRawFileResponse(
57-
is_attached=is_attached(request.volume_id),
57+
is_attached=volume_manager.is_attached(request.volume_id),
5858
status=internal_pb2.ExpandRawFileStatus.OK,
5959
)
6060

6161
if get_capacity() < size_inc:
6262
return internal_pb2.ExpandRawFileResponse(
63-
is_attached=is_attached(request.volume_id),
63+
is_attached=volume_manager.is_attached(request.volume_id),
6464
status=internal_pb2.ExpandRawFileStatus.RESOURCE_EXHAUSTED,
6565
)
6666
if metadata(request.volume_id).get("thin_provision", False):
@@ -72,7 +72,7 @@ def ExpandRawFile(
7272
{"size": request.new_size},
7373
)
7474
return internal_pb2.ExpandRawFileResponse(
75-
is_attached=is_attached(request.volume_id),
75+
is_attached=volume_manager.is_attached(request.volume_id),
7676
status=internal_pb2.ExpandRawFileStatus.OK,
7777
)
7878

rawfile/rawfile.py

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,32 @@
2222
import os
2323

2424

25-
def node_driver_preflight_checks():
25+
def __create_and_check_directory(dir: Path):
26+
if not dir.exists():
27+
logger.info("Creating directory", path=str(dir))
28+
dir.mkdir(parents=True, exist_ok=True)
29+
if not dir.is_dir():
30+
raise RuntimeError(f"{dir} is not a directory")
31+
if not os.access(dir, os.W_OK | os.R_OK | os.X_OK):
32+
raise RuntimeError(f"{dir} is not accessible")
33+
dir.chmod(consts.D_PERMS)
34+
35+
36+
def node_driver_preflight_checks(task_manager: task_manager.TaskManager):
37+
if not config.csi_driver:
38+
raise RuntimeError("CSI Driver configuration is missing")
39+
if not config.csi_driver.metadata_dir:
40+
raise RuntimeError("Metadata directory is not set for node plugin")
2641
data_dir = Path(consts.DATA_DIR)
27-
if not data_dir.exists():
28-
logger.info("Creating data directory", path=str(data_dir))
29-
data_dir.mkdir(parents=True, exist_ok=True)
30-
if not data_dir.is_dir():
31-
raise RuntimeError(f"{data_dir} is not a directory")
32-
if not os.access(data_dir, os.W_OK | os.R_OK | os.X_OK):
33-
raise RuntimeError(f"{data_dir} is not accessible")
34-
data_dir.chmod(consts.D_PERMS)
42+
dirs = (
43+
config.csi_driver.metadata_dir,
44+
data_dir,
45+
)
46+
for dir in dirs:
47+
__create_and_check_directory(dir)
48+
volume_manager.migrate_metadata_dir()
3549
volume_manager.migrate_all_volume_schemas()
50+
task_manager.migrate_tasks_file_path()
3651
consts.COW_SUPPORTED = is_cow_supported(data_dir)
3752

3853

@@ -54,7 +69,10 @@ def csi_driver(driver_config: CSIDriverCmd):
5469
futures.ThreadPoolExecutor(max_workers=int(driver_config.grpc_workers))
5570
)
5671
bg_task_executor = ThreadPoolExecutor(max_workers=5)
57-
_task_manager = task_manager.TaskManager(bg_task_executor)
72+
_task_manager = task_manager.TaskManager(
73+
bg_task_executor,
74+
tasks_store_path=Path(f"{driver_config.metadata_dir}/tasks.json"),
75+
)
5876
internal_server = None
5977
csi_pb2_grpc.add_IdentityServicer_to_server(
6078
bd2fs.Bd2FsIdentityServicer(
@@ -63,7 +81,7 @@ def csi_driver(driver_config: CSIDriverCmd):
6381
server,
6482
)
6583
if driver_config.plugin_type == "node":
66-
node_driver_preflight_checks()
84+
node_driver_preflight_checks(task_manager=_task_manager)
6785
csi_pb2_grpc.add_NodeServicer_to_server(
6886
bd2fs.Bd2FsNodeServicer(
6987
rawfile_servicer.RawFileNodeServicer(node_name=driver_config.nodeid),

rawfile/utils/rawfile.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
from typing import Any
55

66
from utils.logs import logger
7-
8-
from consts import D_PERMS, DATA_DIR, F_PERMS, OWNER_UMASK
7+
from config import config
8+
from consts import D_PERMS, F_PERMS, OWNER_UMASK
99
import os
1010
from enum import Enum
1111
from utils.commands import run
@@ -17,20 +17,20 @@ class AccessType(Enum):
1717
block = 2
1818

1919

20-
def img_dir(volume_id):
21-
return Path(f"{DATA_DIR}/{volume_id}")
20+
def meta_dir(volume_id):
21+
return Path(f"{config.csi_driver.metadata_dir}/{volume_id}")
2222

2323

2424
def meta_file(volume_id):
25-
return Path(f"{img_dir(volume_id)}/disk.meta")
25+
return Path(f"{meta_dir(volume_id)}/disk.meta")
2626

2727

2828
def meta_file_tmp(volume_id):
29-
return Path(f"{img_dir(volume_id)}/disk.meta.tmp")
29+
return Path(f"{meta_dir(volume_id)}/disk.meta.tmp")
3030

3131

3232
def lock_file(volume_id):
33-
return Path(f"{img_dir(volume_id)}/disk.lock")
33+
return Path(f"{meta_dir(volume_id)}/disk.lock")
3434

3535

3636
def metadata(volume_id) -> dict[str, Any]:
@@ -49,9 +49,11 @@ def img_file(volume_id):
4949

5050

5151
def snapshots_dir(volume_id: str, temporary: bool = False):
52+
from utils.volume_manager import manager as volume_manager
53+
5254
if temporary:
53-
return Path(f"{img_dir(volume_id)}/snapshots/temp")
54-
return Path(f"{img_dir(volume_id)}/snapshots")
55+
return Path(f"{volume_manager._get_volume_path(volume_id)}/snapshots/temp")
56+
return Path(f"{volume_manager._get_volume_path(volume_id)}/snapshots")
5557

5658

5759
def img_size(volume_id) -> int:
@@ -89,11 +91,18 @@ def update_metadata(volume_id: str, obj: dict) -> dict:
8991

9092

9193
def update_permissions(volume_id: str) -> None:
92-
_img_dir = img_dir(volume_id)
94+
from utils.volume_manager import manager as volume_manager
95+
from itertools import chain
96+
97+
_img_dir = volume_manager._get_volume_path(volume_id)
9398
if not _img_dir.exists():
9499
return
95100
_img_dir.chmod(D_PERMS)
96-
for each in _img_dir.glob("**/*"):
101+
## set permissions recursively on all files and dirs under the volume path
102+
# we go 3 levels deep to cover most cases (img file, snapshots, temp snapshots, etc.)
103+
for each in chain(
104+
_img_dir.glob("**/*"), _img_dir.glob("**/**/*"), _img_dir.glob("**/**/**/*")
105+
):
97106
each.chmod(F_PERMS)
98107

99108

rawfile/utils/remote.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,3 @@
55
def get_capacity():
66
cap = utils.storage_pool.get_capacity()
77
return max(0, cap)
8-
9-
10-
def is_attached(volume_id):
11-
img_dir = utils.rawfile.img_dir(volume_id)
12-
if not img_dir.exists():
13-
return False
14-
15-
img_file = utils.rawfile.img_file(volume_id)
16-
loops = utils.rawfile.attached_loops(img_file.as_posix())
17-
return len(loops) > 0

rawfile/utils/task_manager.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from concurrent.futures import Executor, Future
22
from enum import StrEnum
3+
import shutil
34
from typing import Callable, TypedDict
45
import time
56
import consts
@@ -45,13 +46,15 @@ class TaskInfo(TypedDict):
4546

4647

4748
class TaskManager:
48-
def __init__(self, executor: Executor, retry_interval=5, max_retry=5):
49+
def __init__(
50+
self, executor: Executor, tasks_store_path: Path, retry_interval=5, max_retry=5
51+
):
4952
self._executor = executor
5053
self._tasks: dict = {}
5154
self._shutting_down = False
5255
self._retry_interval = retry_interval
5356
self._max_retry = max_retry
54-
self._tasks_store_path = Path(f"{consts.DATA_DIR}/tasks.json")
57+
self._tasks_store_path = tasks_store_path
5558
self._tasks_store_path.parent.mkdir(exist_ok=True, parents=True)
5659
self._tasks_store_path.touch(exist_ok=True)
5760
self._lock = Lock()
@@ -94,7 +97,7 @@ def get_tasks(
9497
self, state: TaskState | None = None, retriable: bool | None = None
9598
) -> dict[str, TaskInfo]:
9699
with self._lock:
97-
with open(f"{consts.DATA_DIR}/tasks.json") as tasks_file:
100+
with open(self._tasks_store_path) as tasks_file:
98101
data = json.loads(tasks_file.read() or "{}")
99102
if retriable is not None:
100103
if retriable:
@@ -198,3 +201,9 @@ def shutdown(self, timeout: int):
198201
info["state"] = TaskState.FAILED
199202
self.save_task(task_id, info)
200203
self._executor.shutdown(wait=False, cancel_futures=True)
204+
205+
def migrate_tasks_file_path(self):
206+
src = Path(f"{consts.DATA_DIR}/tasks.json")
207+
dst = self._tasks_store_path
208+
if src.exists():
209+
shutil.move(src, dst)

0 commit comments

Comments
 (0)