]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/pybind/rbd/rbd.pyx
update sources to 12.2.7
[ceph.git] / ceph / src / pybind / rbd / rbd.pyx
index 772085c1ee92bc2cdcaa970f7d2a20b61700cb70..4738b3c197415cbdb919a7eca7bbb4747d3a04b0 100644 (file)
@@ -228,10 +228,12 @@ cdef extern from "rbd/librbd.h" nogil:
                             uint8_t enabled)
     int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit)
     int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count)
+    int rbd_get_create_timestamp(rbd_image_t image, timespec *timestamp)
     int rbd_get_overlap(rbd_image_t image, uint64_t *overlap)
     int rbd_get_id(rbd_image_t image, char *id, size_t id_len)
     int rbd_get_block_name_prefix(rbd_image_t image, char *prefix,
                                   size_t prefix_len)
+    int64_t rbd_get_data_pool_id(rbd_image_t image)
     int rbd_get_parent_info2(rbd_image_t image,
                              char *parent_poolname, size_t ppoolnamelen,
                              char *parent_name, size_t pnamelen,
@@ -387,13 +389,18 @@ class Error(Exception):
 
 class OSError(Error):
     """ `OSError` class, derived from `Error` """
-    def __init__(self, errno, strerror):
+    def __init__(self, message, errno=None):
+        super(OSError, self).__init__(message)
         self.errno = errno
-        self.strerror = strerror
 
     def __str__(self):
-        return '[Errno {0}] {1}'.format(self.errno, self.strerror)
+        msg = super(OSError, self).__str__()
+        if self.errno is None:
+            return msg
+        return '[errno {0}] {1}'.format(self.errno, msg)
 
+    def __reduce__(self):
+        return (self.__class__, (self.message, self.errno))
 
 class PermissionError(OSError):
     pass
@@ -487,9 +494,9 @@ cdef make_ex(ret, msg):
     """
     ret = abs(ret)
     if ret in errno_to_exception:
-        return errno_to_exception[ret](ret, msg)
+        return errno_to_exception[ret](msg, errno=ret)
     else:
-        return Error(ret, msg + (": error code %d" % ret))
+        return OSError(msg, errno=ret)
 
 
 cdef rados_ioctx_t convert_ioctx(rados.Ioctx ioctx) except? NULL:
@@ -513,7 +520,9 @@ def cstr(val, name, encoding="utf-8", opt=False):
         return None
     if isinstance(val, bytes):
         return val
-    elif isinstance(val, unicode):
+    elif isinstance(val, str):
+        return val.encode(encoding)
+    elif sys.version_info < (3, 0) and isinstance(val, unicode):
         return val.encode(encoding)
     else:
         raise InvalidArgument('%s must be a string' % name)
@@ -698,6 +707,7 @@ class RBD(object):
         :raises: :class:`FunctionNotSupported`
         """
         name = cstr(name, 'name')
+        data_pool = cstr(data_pool, 'data_pool', opt=True)
         cdef:
             rados_ioctx_t _ioctx = convert_ioctx(ioctx)
             char *_name = name
@@ -781,6 +791,7 @@ class RBD(object):
         p_snapname = cstr(p_snapname, 'p_snapname')
         p_name = cstr(p_name, 'p_name')
         c_name = cstr(c_name, 'c_name')
+        data_pool = cstr(data_pool, 'data_pool', opt=True)
         cdef:
             rados_ioctx_t _p_ioctx = convert_ioctx(p_ioctx)
             rados_ioctx_t _c_ioctx = convert_ioctx(c_ioctx)
@@ -891,7 +902,7 @@ class RBD(object):
 
     def trash_move(self, ioctx, name, delay=0):
         """
-        Moves an RBD image to the trash.
+        Move an RBD image to the trash.
         :param ioctx: determines which RADOS pool the image is in
         :type ioctx: :class:`rados.Ioctx`
         :param name: the name of the image to remove
@@ -913,7 +924,7 @@ class RBD(object):
 
     def trash_remove(self, ioctx, image_id, force=False):
         """
-        Deletes an RBD image from trash. If image deferment time has not
+        Delete an RBD image from trash. If image deferment time has not
         expired :class:`PermissionError` is raised.
         :param ioctx: determines which RADOS pool the image is in
         :type ioctx: :class:`rados.Ioctx`
@@ -970,15 +981,15 @@ class RBD(object):
             'id'          : decode_cstr(c_info.id),
             'name'        : decode_cstr(c_info.name),
             'source'      : __source_string[c_info.source],
-            'deletion_time' : datetime.fromtimestamp(c_info.deletion_time),
-            'deferment_end_time' : datetime.fromtimestamp(c_info.deferment_end_time)
+            'deletion_time' : datetime.utcfromtimestamp(c_info.deletion_time),
+            'deferment_end_time' : datetime.utcfromtimestamp(c_info.deferment_end_time)
             }
         rbd_trash_get_cleanup(&c_info)
         return info
 
     def trash_list(self, ioctx):
         """
-        Lists all entries from trash.
+        List all entries from trash.
         :param ioctx: determines which RADOS pool the image is in
         :type ioctx: :class:`rados.Ioctx`
         :returns: :class:`TrashIterator`
@@ -987,7 +998,7 @@ class RBD(object):
 
     def trash_restore(self, ioctx, image_id, name):
         """
-        Restores an RBD image from trash.
+        Restore an RBD image from trash.
         :param ioctx: determines which RADOS pool the image is in
         :type ioctx: :class:`rados.Ioctx`
         :param image_id: the id of the image to restore
@@ -1280,7 +1291,7 @@ cdef class MirrorImageStatusIterator(object):
                         },
                     'state'       : self.images[i].state,
                     'description' : decode_cstr(self.images[i].description),
-                    'last_update' : datetime.fromtimestamp(self.images[i].last_update),
+                    'last_update' : datetime.utcfromtimestamp(self.images[i].last_update),
                     'up'          : self.images[i].up,
                     }
             if self.size < self.max_read:
@@ -1543,6 +1554,14 @@ cdef class Image(object):
         finally:
             free(prefix)
 
+    def data_pool_id(self):
+        """
+        Get the pool id of the pool where the data of this RBD image is stored.
+
+        :returns: int - the pool id
+        """
+        return rbd_get_data_pool_id(self.image)
+
     def parent_info(self):
         """
         Get information about a cloned image's parent (if any)
@@ -1631,7 +1650,7 @@ cdef class Image(object):
 
     def features(self):
         """
-        Gets the features bitmask of the image.
+        Get the features bitmask of the image.
 
         :returns: int - the features bitmask of the image
         """
@@ -1644,7 +1663,7 @@ cdef class Image(object):
 
     def update_features(self, features, enabled):
         """
-        Updates the features bitmask of the image by enabling/disabling
+        Update the features bitmask of the image by enabling/disabling
         a single feature.  The feature must support the ability to be
         dynamically enabled/disabled.
 
@@ -1665,7 +1684,7 @@ cdef class Image(object):
 
     def overlap(self):
         """
-        Gets the number of overlapping bytes between the image and its parent
+        Get the number of overlapping bytes between the image and its parent
         image. If open to a snapshot, returns the overlap between the snapshot
         and the parent image.
 
@@ -1681,7 +1700,7 @@ cdef class Image(object):
 
     def flags(self):
         """
-        Gets the flags bitmask of the image.
+        Get the flags bitmask of the image.
 
         :returns: int - the flags bitmask of the image
         """
@@ -1694,7 +1713,7 @@ cdef class Image(object):
 
     def is_exclusive_lock_owner(self):
         """
-        Gets the status of the image exclusive lock.
+        Get the status of the image exclusive lock.
 
         :returns: bool - true if the image is exclusively locked
         """
@@ -1731,6 +1750,7 @@ cdef class Image(object):
         :raises: :class:`ArgumentOutOfRange`
         """
         dest_name = cstr(dest_name, 'dest_name')
+        data_pool = cstr(data_pool, 'data_pool', opt=True)
         cdef:
             rados_ioctx_t _dest_ioctx = convert_ioctx(dest_ioctx)
             char *_dest_name = dest_name
@@ -1945,7 +1965,7 @@ cdef class Image(object):
             ret = rbd_snap_get_timestamp(self.image, _snap_id, &timestamp)
         if ret != 0:
             raise make_ex(ret, 'error getting snapshot timestamp for image: %s, snap_id: %d' % (self.name, snap_id))
-        return datetime.fromtimestamp(timestamp.tv_sec)
+        return datetime.utcfromtimestamp(timestamp.tv_sec)
 
     def remove_snap_limit(self):
         """
@@ -2144,7 +2164,7 @@ written." % (self.name, ret, length))
 
     def stripe_unit(self):
         """
-        Returns the stripe unit used for the image.
+        Return the stripe unit used for the image.
         """
         cdef uint64_t stripe_unit
         with nogil:
@@ -2155,7 +2175,7 @@ written." % (self.name, ret, length))
 
     def stripe_count(self):
         """
-        Returns the stripe count used for the image.
+        Return the stripe count used for the image.
         """
         cdef uint64_t stripe_count
         with nogil:
@@ -2164,6 +2184,18 @@ written." % (self.name, ret, length))
             raise make_ex(ret, 'error getting stripe count for image %s' % (self.name))
         return stripe_count
 
+    def create_timestamp(self):
+        """
+        Return the create timestamp for the image.
+        """
+        cdef:
+            timespec timestamp
+        with nogil:
+            ret = rbd_get_create_timestamp(self.image, &timestamp)
+        if ret != 0:
+            raise make_ex(ret, 'error getting create timestamp for image: %s' % (self.name))
+        return datetime.utcfromtimestamp(timestamp.tv_sec)
+
     def flatten(self):
         """
         Flatten clone image (copy all blocks from parent to child)
@@ -2175,7 +2207,7 @@ written." % (self.name, ret, length))
 
     def rebuild_object_map(self):
         """
-        Rebuilds the object map for the image HEAD or currently set snapshot
+        Rebuild the object map for the image HEAD or currently set snapshot
         """
         cdef librbd_progress_fn_t prog_cb = &no_op_progress_callback
         with nogil:
@@ -2490,7 +2522,7 @@ written." % (self.name, ret, length))
                 },
             'state'       : c_status.state,
             'description' : decode_cstr(c_status.description),
-            'last_update' : datetime.fromtimestamp(c_status.last_update),
+            'last_update' : datetime.utcfromtimestamp(c_status.last_update),
             'up'          : c_status.up,
             }
         free(c_status.name)
@@ -2664,9 +2696,11 @@ written." % (self.name, ret, length))
                     ret = rbd_metadata_get(self.image, _key, value, &size)
                 if ret != -errno.ERANGE:
                     break
+            if ret == -errno.ENOENT:
+                raise KeyError('no metadata %s for image %s' % (key, self.name))
             if ret != 0:
                 raise make_ex(ret, 'error getting metadata %s for image %s' %
-                              (self.key, self.name,))
+                              (key, self.name,))
             return decode_cstr(value)
         finally:
             free(value)
@@ -2690,7 +2724,7 @@ written." % (self.name, ret, length))
 
         if ret != 0:
             raise make_ex(ret, 'error setting metadata %s for image %s' %
-                          (self.key, self.name,))
+                          (key, self.name,))
 
 
     def metadata_remove(self, key):
@@ -2706,9 +2740,11 @@ written." % (self.name, ret, length))
         with nogil:
             ret = rbd_metadata_remove(self.image, _key)
 
+        if ret == -errno.ENOENT:
+            raise KeyError('no metadata %s for image %s' % (key, self.name))
         if ret != 0:
             raise make_ex(ret, 'error removing metadata %s for image %s' %
-                          (self.key, self.name,))
+                          (key, self.name,))
 
     def metadata_list(self):
         """
@@ -2798,6 +2834,10 @@ cdef class MetadataIterator(object):
                 break
             self.get_next_chunk()
 
+    def __dealloc__(self):
+        if self.last_read:
+            free(self.last_read)
+
     def get_next_chunk(self):
         cdef:
             char *c_keys = NULL
@@ -2854,8 +2894,8 @@ cdef class SnapIterator(object):
         self.num_snaps = 10
         while True:
             self.snaps = <rbd_snap_info_t*>realloc_chk(self.snaps,
-                                                   self.num_snaps *
-                                                   sizeof(rbd_snap_info_t))
+                                                       self.num_snaps *
+                                                       sizeof(rbd_snap_info_t))
             with nogil:
                 ret = rbd_snap_list(image.image, self.snaps, &self.num_snaps)
             if ret >= 0:
@@ -2905,12 +2945,18 @@ cdef class TrashIterator(object):
     def __init__(self, ioctx):
         self.ioctx = convert_ioctx(ioctx)
         self.num_entries = 1024
-        self.entries = <rbd_trash_image_info_t *>realloc_chk(NULL,
-            sizeof(rbd_trash_image_info_t) * self.num_entries)
-        with nogil:
-            ret = rbd_trash_list(self.ioctx, self.entries, &self.num_entries)
-        if ret < 0:
-            raise make_ex(ret, 'error listing trash entries')
+        self.entries = NULL
+        while True:
+            self.entries = <rbd_trash_image_info_t*>realloc_chk(self.entries,
+                                                                self.num_entries *
+                                                                sizeof(rbd_trash_image_info_t))
+            with nogil:
+                ret = rbd_trash_list(self.ioctx, self.entries, &self.num_entries)
+            if ret >= 0:
+                self.num_entries = ret
+                break
+            elif ret != -errno.ERANGE:
+                raise make_ex(ret, 'error listing trash entries')
 
     __source_string = ['USER', 'MIRRORING']
 
@@ -2920,8 +2966,8 @@ cdef class TrashIterator(object):
                 'id'          : decode_cstr(self.entries[i].id),
                 'name'        : decode_cstr(self.entries[i].name),
                 'source'      : TrashIterator.__source_string[self.entries[i].source],
-                'deletion_time' : datetime.fromtimestamp(self.entries[i].deletion_time),
-                'deferment_end_time' : datetime.fromtimestamp(self.entries[i].deferment_end_time)
+                'deletion_time' : datetime.utcfromtimestamp(self.entries[i].deletion_time),
+                'deferment_end_time' : datetime.utcfromtimestamp(self.entries[i].deferment_end_time)
                 }
 
     def __dealloc__(self):