Skip to content

Commit 35e572d

Browse files
ema-aka-youngjpeimerrnetser
authored
refactor: update DataVolume resource (#2480) (#2723)
Co-authored-by: Jenia Peimer <86722603+jpeimer@users.noreply.github.com> Co-authored-by: Ruth Netser <rnetser@redhat.com>
1 parent f6cae90 commit 35e572d

1 file changed

Lines changed: 117 additions & 85 deletions

File tree

ocp_resources/datavolume.py

Lines changed: 117 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
from ocp_resources.utils.constants import (
24
TIMEOUT_1MINUTE,
35
TIMEOUT_2MINUTES,
@@ -10,6 +12,11 @@
1012
from timeout_sampler import TimeoutExpiredError, TimeoutSampler
1113
from warnings import warn
1214

15+
from typing import Any, TYPE_CHECKING
16+
17+
if TYPE_CHECKING:
18+
from ocp_resources.secret import Secret
19+
1320

1421
class DataVolume(NamespacedResource):
1522
"""
@@ -70,69 +77,58 @@ class Status(Resource.Condition.Status):
7077

7178
def __init__(
7279
self,
73-
name=None,
74-
namespace=None,
75-
source=None,
76-
size=None,
77-
storage_class=None,
78-
url=None,
79-
content_type=ContentType.KUBEVIRT,
80-
access_modes=None,
81-
cert_configmap=None,
82-
secret=None,
83-
client=None,
84-
volume_mode=None,
85-
hostpath_node=None,
86-
source_pvc=None,
87-
source_namespace=None,
88-
multus_annotation=None,
89-
bind_immediate_annotation=None,
90-
preallocation=None,
91-
teardown=True,
92-
yaml_file=None,
93-
delete_timeout=TIMEOUT_4MINUTES,
94-
api_name="pvc",
95-
delete_after_completion=None,
96-
**kwargs,
97-
):
80+
source: str | None = None,
81+
source_dict: dict[str, Any] | None = None,
82+
size: str | None = None,
83+
storage_class: str | None = None,
84+
url: str | None = None,
85+
content_type: str | None = None,
86+
access_modes: str | None = None,
87+
volume_mode: str | None = None,
88+
cert_configmap: str | None = None,
89+
secret: Secret | None = None,
90+
hostpath_node: str | None = None,
91+
source_pvc: str | None = None,
92+
source_namespace: str | None = None,
93+
source_ref: dict[str, Any] | None = None,
94+
multus_annotation: str | None = None,
95+
bind_immediate_annotation: bool | None = None,
96+
preallocation: bool | None = None,
97+
api_name: str | None = "pvc",
98+
checkpoints: list[Any] | None = None,
99+
final_checkpoint: bool | None = None,
100+
priority_class_name: str | None = None,
101+
**kwargs: Any,
102+
) -> None:
98103
"""
99104
DataVolume object
100105
101106
Args:
102-
name (str): DataVolume name.
103-
namespace (str): DataVolume namespace.
104-
source (str): source of DV - upload/http/pvc/registry.
105-
size (str): DataVolume size - format size+size unit, for example: "5Gi".
107+
source (str, default: None): source of DV - upload/http/pvc/registry/blank.
108+
source_dict (dict[str, Any], default: None): DataVolume.source dictionary.
109+
size (str, default: None): DataVolume size - format size+size unit, for example: "5Gi".
106110
storage_class (str, default: None): storage class name for DataVolume.
107111
url (str, default: None): url for importing DV, when source is http/registry.
108-
content_type (str, default: "kubevirt"): DataVolume content type.
109-
access_modes (str, default: None): DataVolume access mode.
112+
content_type (str, default: None): DataVolume content type (e.g., "kubevirt", "archive").
113+
access_modes (str, default: None): DataVolume access mode (e.g., "ReadWriteOnce", "ReadWriteMany").
114+
volume_mode (str, default: None): DataVolume volume mode (e.g., "Filesystem", "Block").
110115
cert_configmap (str, default: None): name of config map for TLS certificates.
111116
secret (Secret, default: None): to be set as secretRef.
112-
client (DynamicClient): DynamicClient to use.
113-
volume_mode (str, default: None): DataVolume volume mode.
114117
hostpath_node (str, default: None): Node name to provision the DV on.
115118
source_pvc (str, default: None): PVC name for when cloning the DV.
116119
source_namespace (str, default: None): PVC namespace for when cloning the DV.
120+
source_ref (dict[str, Any], default: None): SourceRef is an indirect reference to the source of data for the
121+
requested DataVolume. Currently only "DataSource" is supported. Fields: kind (str), name (str), namespace (str)
117122
multus_annotation (str, default: None): network nad name.
118-
bind_immediate_annotation (bool, default: None): when WaitForFirstConsumer is set in StorageClass and DV
119-
should be bound immediately.
123+
bind_immediate_annotation (bool, default: None): when WaitForFirstConsumer is set in StorageClass and DV
124+
should be bound immediately.
120125
preallocation (bool, default: None): preallocate disk space.
121-
teardown (bool, default: True): Indicates if this resource would need to be deleted.
122-
yaml_file (yaml, default: None): yaml file for the resource.
123-
delete_timeout (int, default: 4 minutes): timeout associated with delete action.
124-
api_name (str, default: "pvc"): api used for DV, pvc/storage
125-
delete_after_completion (str, default: None): annotation for garbage collector - "true"/"false"
126+
api_name (str, default: "pvc"): api used for DV (e.g., "storage", "pvc").
127+
checkpoints (list[Any], default: None): list of DataVolumeCheckpoints for snapshot operations.
128+
final_checkpoint (bool, default: None): indicates whether the current DataVolumeCheckpoint is the final one.
129+
priority_class_name (str, default: None): priority class name for the DataVolume pod.
126130
"""
127-
super().__init__(
128-
name=name,
129-
namespace=namespace,
130-
client=client,
131-
teardown=teardown,
132-
yaml_file=yaml_file,
133-
delete_timeout=delete_timeout,
134-
**kwargs,
135-
)
131+
super().__init__(**kwargs)
136132
self.source = source
137133
self.url = url
138134
self.cert_configmap = cert_configmap
@@ -145,62 +141,98 @@ def __init__(
145141
self.hostpath_node = hostpath_node
146142
self.source_pvc = source_pvc
147143
self.source_namespace = source_namespace
144+
self.source_dict = source_dict
145+
self.source_ref = source_ref
148146
self.multus_annotation = multus_annotation
149147
self.bind_immediate_annotation = bind_immediate_annotation
150148
self.preallocation = preallocation
151149
self.api_name = api_name
152-
self.delete_after_completion = delete_after_completion
150+
self.checkpoints = checkpoints
151+
self.final_checkpoint = final_checkpoint
152+
self.priority_class_name = priority_class_name
153153

154154
def to_dict(self) -> None:
155155
super().to_dict()
156156
if not self.kind_dict and not self.yaml_file:
157-
self.res.update({
158-
"spec": {
159-
"source": {self.source: {"url": self.url}},
160-
self.api_name: {
161-
"resources": {"requests": {"storage": self.size}},
162-
},
163-
}
164-
})
165-
if self.access_modes:
166-
self.res["spec"][self.api_name]["accessModes"] = [self.access_modes]
167-
if self.content_type:
168-
self.res["spec"]["contentType"] = self.content_type
169-
if self.storage_class:
170-
self.res["spec"][self.api_name]["storageClassName"] = self.storage_class
171-
if self.secret:
172-
self.res["spec"]["source"][self.source]["secretRef"] = self.secret.name
173-
if self.volume_mode:
174-
self.res["spec"][self.api_name]["volumeMode"] = self.volume_mode
175-
if self.source == "http" or "registry":
176-
self.res["spec"]["source"][self.source]["url"] = self.url
177-
if self.cert_configmap:
178-
self.res["spec"]["source"][self.source]["certConfigMap"] = self.cert_configmap
179-
if self.source == "upload" or self.source == "blank":
180-
self.res["spec"]["source"][self.source] = {}
157+
self.res["spec"] = {}
158+
_spec = self.res["spec"]
159+
160+
if self.checkpoints is not None:
161+
_spec["checkpoints"] = self.checkpoints
162+
163+
if self.content_type is not None:
164+
_spec["contentType"] = self.content_type
165+
166+
if self.final_checkpoint is not None:
167+
_spec["finalCheckpoint"] = self.final_checkpoint
168+
169+
if self.preallocation is not None:
170+
_spec["preallocation"] = self.preallocation
171+
172+
if self.priority_class_name is not None:
173+
_spec["priorityClassName"] = self.priority_class_name
174+
175+
# Set api_name spec fields (pvc/storage)
176+
if self.api_name is not None:
177+
_spec[self.api_name] = {}
178+
179+
if self.access_modes is not None:
180+
_spec[self.api_name]["accessModes"] = [self.access_modes]
181+
182+
if self.volume_mode is not None:
183+
_spec[self.api_name]["volumeMode"] = self.volume_mode
184+
185+
if self.storage_class is not None:
186+
_spec[self.api_name]["storageClassName"] = self.storage_class
187+
188+
if self.size is not None:
189+
_spec[self.api_name]["resources"] = {"requests": {"storage": self.size}}
190+
191+
# Handle source configuration
192+
if self.source_dict is not None:
193+
_spec["source"] = self.source_dict
194+
elif self.source is not None:
195+
warn(
196+
"source is deprecated and will be removed in the next version. Use source_dict instead.",
197+
DeprecationWarning,
198+
stacklevel=2,
199+
)
200+
201+
_spec["source"] = {}
202+
source_spec = _spec["source"]
203+
204+
if self.source in ["http", "registry"]:
205+
source_spec[self.source] = {"url": self.url}
206+
elif self.source in ["upload", "blank"]:
207+
source_spec[self.source] = {}
208+
elif self.source == "pvc":
209+
source_spec[self.source] = {
210+
"name": self.source_pvc,
211+
"namespace": self.source_namespace or self.namespace,
212+
}
213+
214+
if self.secret is not None:
215+
source_spec[self.source]["secretRef"] = self.secret.name
216+
if self.cert_configmap is not None:
217+
source_spec[self.source]["certConfigMap"] = self.cert_configmap
218+
219+
if self.source_ref is not None:
220+
_spec["sourceRef"] = self.source_ref
221+
181222
if self.hostpath_node:
182223
self.res["metadata"].setdefault("annotations", {}).update({
183224
f"{NamespacedResource.ApiGroup.KUBEVIRT_IO}/provisionOnNode": (self.hostpath_node)
184225
})
226+
185227
if self.multus_annotation:
186228
self.res["metadata"].setdefault("annotations", {}).update({
187229
f"{NamespacedResource.ApiGroup.K8S_V1_CNI_CNCF_IO}/networks": (self.multus_annotation)
188230
})
231+
189232
if self.bind_immediate_annotation:
190233
self.res["metadata"].setdefault("annotations", {}).update({
191234
f"{self.api_group}/storage.bind.immediate.requested": "true"
192235
})
193-
if self.source == "pvc":
194-
self.res["spec"]["source"]["pvc"] = {
195-
"name": self.source_pvc or "dv-source",
196-
"namespace": self.source_namespace or self.namespace,
197-
}
198-
if self.preallocation is not None:
199-
self.res["spec"]["preallocation"] = self.preallocation
200-
if self.delete_after_completion:
201-
self.res["metadata"].setdefault("annotations", {}).update({
202-
f"{self.api_group}/storage.deleteAfterCompletion": (self.delete_after_completion)
203-
})
204236

205237
def wait_deleted(self, timeout=TIMEOUT_4MINUTES):
206238
"""

0 commit comments

Comments
 (0)