Skip to content

Commit 92f82d6

Browse files
authored
Merge pull request ceph#58265 from idryomov/wip-rbd-pybind-utc-timestamps
pybind/rbd: change to return "aware" datetime objects Reviewed-by: Ramana Raja <[email protected]>
2 parents 6e42fb9 + c31d307 commit 92f82d6

File tree

3 files changed

+31
-16
lines changed

3 files changed

+31
-16
lines changed

PendingReleaseNotes

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
>=20.0.0
2+
3+
* RBD: All Python APIs that produce timestamps now return "aware" `datetime`
4+
objects instead of "naive" ones (i.e. those including time zone information
5+
instead of those not including it). All timestamps remain to be in UTC but
6+
including `timezone.utc` makes it explicit and avoids the potential of the
7+
returned timestamp getting misinterpreted -- in Python 3, many `datetime`
8+
methods treat "naive" `datetime` objects as local times.
9+
110
>=19.0.0
211

312
* cephx: key rotation is now possible using `ceph auth rotate`. Previously,

src/pybind/rbd/rbd.pyx

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ try:
2929
from collections.abc import Iterable
3030
except ImportError:
3131
from collections import Iterable
32-
from datetime import datetime
32+
from datetime import datetime, timezone
3333
import errno
3434
from itertools import chain
3535
import time
@@ -935,8 +935,10 @@ class RBD(object):
935935
'id' : decode_cstr(c_info.id),
936936
'name' : decode_cstr(c_info.name),
937937
'source' : __source_string[c_info.source],
938-
'deletion_time' : datetime.utcfromtimestamp(c_info.deletion_time),
939-
'deferment_end_time' : datetime.utcfromtimestamp(c_info.deferment_end_time)
938+
'deletion_time' : datetime.fromtimestamp(c_info.deletion_time,
939+
tz=timezone.utc),
940+
'deferment_end_time' : datetime.fromtimestamp(c_info.deferment_end_time,
941+
tz=timezone.utc)
940942
}
941943
rbd_trash_get_cleanup(&c_info)
942944
return info
@@ -2296,7 +2298,8 @@ cdef class MirrorImageStatusIterator(object):
22962298
site_status = {
22972299
'state' : s_status.state,
22982300
'description' : decode_cstr(s_status.description),
2299-
'last_update' : datetime.utcfromtimestamp(s_status.last_update),
2301+
'last_update' : datetime.fromtimestamp(s_status.last_update,
2302+
tz=timezone.utc),
23002303
'up' : s_status.up,
23012304
}
23022305
mirror_uuid = decode_cstr(s_status.mirror_uuid)
@@ -3814,7 +3817,7 @@ cdef class Image(object):
38143817
ret = rbd_snap_get_timestamp(self.image, _snap_id, &timestamp)
38153818
if ret != 0:
38163819
raise make_ex(ret, 'error getting snapshot timestamp for image: %s, snap_id: %d' % (self.name, snap_id))
3817-
return datetime.utcfromtimestamp(timestamp.tv_sec)
3820+
return datetime.fromtimestamp(timestamp.tv_sec, tz=timezone.utc)
38183821

38193822
@requires_not_closed
38203823
def remove_snap_limit(self):
@@ -4136,7 +4139,7 @@ written." % (self.name, ret, length))
41364139
ret = rbd_get_create_timestamp(self.image, &timestamp)
41374140
if ret != 0:
41384141
raise make_ex(ret, 'error getting create timestamp for image: %s' % (self.name))
4139-
return datetime.utcfromtimestamp(timestamp.tv_sec)
4142+
return datetime.fromtimestamp(timestamp.tv_sec, tz=timezone.utc)
41404143

41414144
@requires_not_closed
41424145
def access_timestamp(self):
@@ -4149,7 +4152,7 @@ written." % (self.name, ret, length))
41494152
ret = rbd_get_access_timestamp(self.image, &timestamp)
41504153
if ret != 0:
41514154
raise make_ex(ret, 'error getting access timestamp for image: %s' % (self.name))
4152-
return datetime.utcfromtimestamp(timestamp.tv_sec)
4155+
return datetime.fromtimestamp(timestamp.tv_sec, tz=timezone.utc)
41534156

41544157
@requires_not_closed
41554158
def modify_timestamp(self):
@@ -4162,7 +4165,7 @@ written." % (self.name, ret, length))
41624165
ret = rbd_get_modify_timestamp(self.image, &timestamp)
41634166
if ret != 0:
41644167
raise make_ex(ret, 'error getting modify timestamp for image: %s' % (self.name))
4165-
return datetime.utcfromtimestamp(timestamp.tv_sec)
4168+
return datetime.fromtimestamp(timestamp.tv_sec, tz=timezone.utc)
41664169

41674170
@requires_not_closed
41684171
def flatten(self, on_progress=None):
@@ -4733,7 +4736,8 @@ written." % (self.name, ret, length))
47334736
site_status = {
47344737
'state' : s_status.state,
47354738
'description' : decode_cstr(s_status.description),
4736-
'last_update' : datetime.utcfromtimestamp(s_status.last_update),
4739+
'last_update' : datetime.fromtimestamp(s_status.last_update,
4740+
tz=timezone.utc),
47374741
'up' : s_status.up,
47384742
}
47394743
mirror_uuid = decode_cstr(s_status.mirror_uuid)
@@ -5703,8 +5707,10 @@ cdef class TrashIterator(object):
57035707
'id' : decode_cstr(self.entries[i].id),
57045708
'name' : decode_cstr(self.entries[i].name),
57055709
'source' : TrashIterator.__source_string[self.entries[i].source],
5706-
'deletion_time' : datetime.utcfromtimestamp(self.entries[i].deletion_time),
5707-
'deferment_end_time' : datetime.utcfromtimestamp(self.entries[i].deferment_end_time)
5710+
'deletion_time' : datetime.fromtimestamp(self.entries[i].deletion_time,
5711+
tz=timezone.utc),
5712+
'deferment_end_time' : datetime.fromtimestamp(self.entries[i].deferment_end_time,
5713+
tz=timezone.utc)
57085714
}
57095715

57105716
def __dealloc__(self):

src/test/pybind/test_rbd.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from assertions import (assert_equal as eq, assert_raises, assert_not_equal,
1515
assert_greater_equal)
16-
from datetime import datetime, timedelta
16+
from datetime import datetime, timedelta, timezone
1717
from rados import (Rados,
1818
LIBRADOS_SNAP_HEAD,
1919
LIBRADOS_OP_FLAG_FADVISE_DONTNEED,
@@ -594,9 +594,9 @@ def setup_method(self, method):
594594
self.rbd = RBD()
595595
# {create,access,modify}_timestamp() have second precision,
596596
# allow for rounding
597-
self.time_before_create = datetime.utcnow() - timedelta(seconds=1)
597+
self.time_before_create = datetime.now(timezone.utc) - timedelta(seconds=1)
598598
create_image()
599-
self.time_after_create = datetime.utcnow() + timedelta(seconds=1)
599+
self.time_after_create = datetime.now(timezone.utc) + timedelta(seconds=1)
600600
self.image = Image(ioctx, image_name)
601601

602602
def teardown_method(self, method):
@@ -1118,9 +1118,9 @@ def test_snap_exists(self):
11181118

11191119
def test_snap_timestamp(self):
11201120
# get_snap_timestamp() has second precision, allow for rounding
1121-
time_before = datetime.utcnow() - timedelta(seconds=1)
1121+
time_before = datetime.now(timezone.utc) - timedelta(seconds=1)
11221122
self.image.create_snap('snap1')
1123-
time_after = datetime.utcnow() + timedelta(seconds=1)
1123+
time_after = datetime.now(timezone.utc) + timedelta(seconds=1)
11241124
eq(['snap1'], [snap['name'] for snap in self.image.list_snaps()])
11251125
for snap in self.image.list_snaps():
11261126
snap_id = snap["id"]

0 commit comments

Comments
 (0)