From 4cb5c31e7bd9ada76b74c891c17cedf91f2fbbc2 Mon Sep 17 00:00:00 2001 From: hamistao Date: Fri, 5 Jul 2024 19:20:09 -0300 Subject: [PATCH] pylxd/models: Adapt JSON parsing for older LXD versions Older LXD versions' APIs don't include: The `created_at` field, the `expires_at` field on /1.0/storage-pools//volumes/custom//snapshots, The `content_type` on /1.0/storage-pools//volumes/custom//snapshots/. Signed-off-by: hamistao --- pylxd/models/storage_pool.py | 53 ++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/pylxd/models/storage_pool.py b/pylxd/models/storage_pool.py index 527b0a3e..a7d90b83 100644 --- a/pylxd/models/storage_pool.py +++ b/pylxd/models/storage_pool.py @@ -669,6 +669,37 @@ def api(self): """ return self.volume.api[self._endpoint][self.name] + @classmethod + def __parse_snaspshot_json(cls, volume, snapshot_json): + snapshot_object = cls(volume.client, volume=volume, **snapshot_json) + + # Snapshot names are namespaced in LXD, as volume-name/snapshot-name. + # We hide that implementation detail. + snapshot_object.name = snapshot_object.name.split("/")[-1] + + # If reponse does not include expires_at sync the object to get that attribute. + if not snapshot_json.get("expires_at"): + snapshot_object.sync() + + # Getting '0001-01-01T00:00:00Z' means that the volume does not have an expiration time set. + if snapshot_object.expires_at == "0001-01-01T00:00:00Z": + snapshot_object.expires_at = None + + # Overriding default value for when created_at is not present on the response due to using LXD 4.0. + # Also having created_at as "0001-01-01T00:00:00Z" means this information is not available. + # This could be because the information was lost or the snapshot was created using an older LXD version. + if ( + not volume.client.has_api_extension("storage_volumes_created_at") + or snapshot_json["created_at"] == "0001-01-01T00:00:00Z" + ): + snapshot_object.created_at = None + + # This field is may empty so derive it from its volume. + if not snapshot_object.content_type: + snapshot_object.content_type = volume.content_type + + return snapshot_object + @classmethod def get(cls, volume, name): """Get a :class:`pylxd.models.StorageVolumeSnapshot` by its name. @@ -692,16 +723,7 @@ def get(cls, volume, name): response = volume.api.snapshots[name].get() - snapshot = cls(volume.client, volume=volume, **response.json()["metadata"]) - - # Getting '0001-01-01T00:00:00Z' means that the volume does not have an expiration time set. - if response.json()["metadata"]["expires_at"] == "0001-01-01T00:00:00Z": - snapshot.expires_at = None - - # Snapshot names are namespaced in LXD, as volume-name/snapshot-name. - # We hide that implementation detail. - snapshot.name = snapshot.name.split("/")[-1] - return snapshot + return cls.__parse_snaspshot_json(volume, response.json()["metadata"]) @classmethod def all(cls, volume, use_recursion=False): @@ -727,19 +749,10 @@ def all(cls, volume, use_recursion=False): if use_recursion: # Using recursion so returning list of StorageVolumeSnapshot objects. - def parse_response_item(snapshot_json): - snapshot_object = cls(volume.client, volume=volume, **snapshot_json) - snapshot_object.content_type = volume.content_type - # Snapshot names are namespaced in LXD, as volume-name/snapshot-name. - # We hide that implementation detail. - snapshot_object.name = snapshot_object.name.split("/")[-1] - - return snapshot_object - response = volume.api.snapshots.get(params={"recursion": 1}) return [ - parse_response_item(snapshot) + cls.__parse_snaspshot_json(volume, snapshot) for snapshot in response.json()["metadata"] ]