]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: refactored mirror peer and image status APIs
authorJason Dillaman <dillaman@redhat.com>
Fri, 20 Sep 2019 19:44:19 +0000 (15:44 -0400)
committerJason Dillaman <dillaman@redhat.com>
Tue, 8 Oct 2019 15:17:15 +0000 (11:17 -0400)
The mirror peer APIs now include the direction, site name, and last seen
timestamp. The mirror image status APIs now include the remote site status
for the image.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
18 files changed:
src/include/rbd/librbd.h
src/include/rbd/librbd.hpp
src/librbd/api/Mirror.cc
src/librbd/api/Mirror.h
src/librbd/librbd.cc
src/pybind/rbd/rbd.pyx
src/test/librbd/test_mirroring.cc
src/test/pybind/test_rbd.py
src/test/rbd_mirror/test_ClusterWatcher.cc
src/test/rbd_mirror/test_PoolWatcher.cc
src/tools/rbd/CMakeLists.txt
src/tools/rbd/Utils.cc
src/tools/rbd/Utils.h
src/tools/rbd/action/MirrorImage.cc
src/tools/rbd/action/MirrorPool.cc
src/tools/rbd_mirror/ClusterWatcher.cc
src/tools/rbd_mirror/ClusterWatcher.h
src/tools/rbd_mirror/Types.h

index 55668b0632784ee5a2c28f196142af986c4f5f96..64af2d3d64aed1be86f5b64363a0943006403866 100644 (file)
@@ -49,14 +49,20 @@ extern "C" {
 #define LIBRBD_SUPPORTS_WRITESAME 1
 
 #if __GNUC__ >= 4
-  #define CEPH_RBD_API    __attribute__ ((visibility ("default")))
+  #define CEPH_RBD_API          __attribute__ ((visibility ("default")))
+  #define CEPH_RBD_DEPRECATED   __attribute__((deprecated))
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 #else
   #define CEPH_RBD_API
+  #define CEPH_RBD_DEPRECATED
 #endif
 
 #define RBD_FLAG_OBJECT_MAP_INVALID   (1<<0)
 #define RBD_FLAG_FAST_DIFF_INVALID    (1<<1)
 
+#define RBD_MIRROR_IMAGE_STATUS_LOCAL_FSID ""
+
 typedef void *rbd_image_t;
 typedef void *rbd_image_options_t;
 typedef void *rbd_pool_stats_t;
@@ -129,7 +135,7 @@ typedef struct {
   uint64_t num_objs;
   int order;
   char block_name_prefix[RBD_MAX_BLOCK_NAME_SIZE]; /* deprecated */
-  int64_t parent_pool;                            /* deprecated */
+  int64_t parent_pool;                             /* deprecated */
   char parent_name[RBD_MAX_IMAGE_NAME_SIZE];       /* deprecated */
 } rbd_image_info_t;
 
@@ -149,7 +155,16 @@ typedef struct {
   char *uuid;
   char *cluster_name;
   char *client_name;
-} rbd_mirror_peer_t;
+} rbd_mirror_peer_t CEPH_RBD_DEPRECATED;
+
+typedef struct {
+  char *uuid;
+  rbd_mirror_peer_direction_t direction;
+  char *site_name;
+  char *fsid;
+  char *client_name;
+  time_t last_seen;
+} rbd_mirror_peer_site_t;
 
 #define RBD_MIRROR_PEER_ATTRIBUTE_NAME_MON_HOST "mon_host"
 #define RBD_MIRROR_PEER_ATTRIBUTE_NAME_KEY      "key"
@@ -183,7 +198,22 @@ typedef struct {
   char *description;
   time_t last_update;
   bool up;
-} rbd_mirror_image_status_t;
+} rbd_mirror_image_status_t CEPH_RBD_DEPRECATED;
+
+typedef struct {
+  char *fsid;
+  rbd_mirror_image_status_state_t state;
+  char *description;
+  time_t last_update;
+  bool up;
+} rbd_mirror_image_site_status_t;
+
+typedef struct {
+  char *name;
+  rbd_mirror_image_info_t info;
+  uint32_t site_statuses_count;
+  rbd_mirror_image_site_status_t *site_statuses;
+} rbd_mirror_image_global_status_t;
 
 typedef enum {
   RBD_GROUP_IMAGE_STATE_ATTACHED,
@@ -335,7 +365,7 @@ CEPH_RBD_API void rbd_snap_spec_cleanup(rbd_snap_spec_t *snap);
 
 /* images */
 CEPH_RBD_API int rbd_list(rados_ioctx_t io, char *names, size_t *size)
-    __attribute__((deprecated));
+  CEPH_RBD_DEPRECATED;
 CEPH_RBD_API int rbd_list2(rados_ioctx_t io, rbd_image_spec_t* images,
                            size_t *max_images);
 
@@ -447,44 +477,86 @@ CEPH_RBD_API int rbd_mirror_mode_get(rados_ioctx_t io_ctx,
 CEPH_RBD_API int rbd_mirror_mode_set(rados_ioctx_t io_ctx,
                                      rbd_mirror_mode_t mirror_mode);
 
-CEPH_RBD_API int rbd_mirror_peer_bootstrap_create(rados_ioctx_t io_ctx,
-                                                  char *token, size_t *max_len);
+CEPH_RBD_API int rbd_mirror_peer_bootstrap_create(
+    rados_ioctx_t io_ctx, char *token, size_t *max_len);
 CEPH_RBD_API int rbd_mirror_peer_bootstrap_import(
     rados_ioctx_t io_ctx, rbd_mirror_peer_direction_t direction,
     const char *token);
 
-CEPH_RBD_API int rbd_mirror_peer_add(rados_ioctx_t io_ctx,
-                                     char *uuid, size_t uuid_max_length,
-                                     const char *cluster_name,
-                                     const char *client_name);
-CEPH_RBD_API int rbd_mirror_peer_remove(rados_ioctx_t io_ctx,
-                                        const char *uuid);
-CEPH_RBD_API int rbd_mirror_peer_list(rados_ioctx_t io_ctx,
-                                      rbd_mirror_peer_t *peers, int *max_peers);
-CEPH_RBD_API void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers,
-                                               int max_peers);
-CEPH_RBD_API int rbd_mirror_peer_set_client(rados_ioctx_t io_ctx,
-                                            const char *uuid,
-                                            const char *client_name);
-CEPH_RBD_API int rbd_mirror_peer_set_cluster(rados_ioctx_t io_ctx,
-                                             const char *uuid,
-                                             const char *cluster_name);
-CEPH_RBD_API int rbd_mirror_peer_get_attributes(
+CEPH_RBD_API int rbd_mirror_peer_site_add(
+    rados_ioctx_t io_ctx, char *uuid, size_t uuid_max_length,
+    rbd_mirror_peer_direction_t direction, const char *site_name,
+    const char *client_name);
+CEPH_RBD_API int rbd_mirror_peer_site_set_name(
+    rados_ioctx_t io_ctx, const char *uuid, const char *site_name);
+CEPH_RBD_API int rbd_mirror_peer_site_set_client_name(
+    rados_ioctx_t io_ctx, const char *uuid, const char *client_name);
+CEPH_RBD_API int rbd_mirror_peer_site_set_direction(
+    rados_ioctx_t io_ctx, const char *uuid,
+    rbd_mirror_peer_direction_t direction);
+CEPH_RBD_API int rbd_mirror_peer_site_remove(
+    rados_ioctx_t io_ctx, const char *uuid);
+CEPH_RBD_API int rbd_mirror_peer_site_list(
+    rados_ioctx_t io_ctx, rbd_mirror_peer_site_t *peers, int *max_peers);
+CEPH_RBD_API void rbd_mirror_peer_site_list_cleanup(
+    rbd_mirror_peer_site_t *peers, int max_peers);
+CEPH_RBD_API int rbd_mirror_peer_site_get_attributes(
     rados_ioctx_t p, const char *uuid, char *keys, size_t *max_key_len,
     char *values, size_t *max_value_len, size_t *key_value_count);
-CEPH_RBD_API int rbd_mirror_peer_set_attributes(
+CEPH_RBD_API int rbd_mirror_peer_site_set_attributes(
     rados_ioctx_t p, const char *uuid, const char *keys, const char *values,
     size_t key_value_count);
 
-CEPH_RBD_API int rbd_mirror_image_status_list(rados_ioctx_t io_ctx,
-                                             const char *start_id, size_t max,
-                                             char **image_ids,
-                                             rbd_mirror_image_status_t *images,
-                                             size_t *len);
-CEPH_RBD_API void rbd_mirror_image_status_list_cleanup(char **image_ids,
-    rbd_mirror_image_status_t *images, size_t len);
-CEPH_RBD_API int rbd_mirror_image_status_summary(rados_ioctx_t io_ctx,
-    rbd_mirror_image_status_state_t *states, int *counts, size_t *maxlen);
+CEPH_RBD_API int rbd_mirror_image_global_status_list(
+    rados_ioctx_t io_ctx, const char *start_id, size_t max, char **image_ids,
+    rbd_mirror_image_global_status_t *images, size_t *len);
+CEPH_RBD_API void rbd_mirror_image_global_status_list_cleanup(
+    char **image_ids, rbd_mirror_image_global_status_t *images, size_t len);
+
+/* rbd_mirror_peer_ commands are deprecated to rbd_mirror_peer_site_
+ * equivalents */
+CEPH_RBD_API int rbd_mirror_peer_add(
+    rados_ioctx_t io_ctx, char *uuid, size_t uuid_max_length,
+    const char *cluster_name, const char *client_name)
+  CEPH_RBD_DEPRECATED;
+CEPH_RBD_API int rbd_mirror_peer_remove(
+    rados_ioctx_t io_ctx, const char *uuid)
+  CEPH_RBD_DEPRECATED;
+CEPH_RBD_API int rbd_mirror_peer_list(
+    rados_ioctx_t io_ctx, rbd_mirror_peer_t *peers, int *max_peers)
+  CEPH_RBD_DEPRECATED;
+CEPH_RBD_API void rbd_mirror_peer_list_cleanup(
+    rbd_mirror_peer_t *peers, int max_peers)
+  CEPH_RBD_DEPRECATED;
+CEPH_RBD_API int rbd_mirror_peer_set_client(
+    rados_ioctx_t io_ctx, const char *uuid, const char *client_name)
+  CEPH_RBD_DEPRECATED;
+CEPH_RBD_API int rbd_mirror_peer_set_cluster(
+    rados_ioctx_t io_ctx, const char *uuid, const char *cluster_name)
+  CEPH_RBD_DEPRECATED;
+CEPH_RBD_API int rbd_mirror_peer_get_attributes(
+    rados_ioctx_t p, const char *uuid, char *keys, size_t *max_key_len,
+    char *values, size_t *max_value_len, size_t *key_value_count)
+  CEPH_RBD_DEPRECATED;
+CEPH_RBD_API int rbd_mirror_peer_set_attributes(
+    rados_ioctx_t p, const char *uuid, const char *keys, const char *values,
+    size_t key_value_count)
+  CEPH_RBD_DEPRECATED;
+
+/* rbd_mirror_image_status_list_ commands are deprecard to
+ * rbd_mirror_image_global_status_list_ commands */
+
+CEPH_RBD_API int rbd_mirror_image_status_list(
+    rados_ioctx_t io_ctx, const char *start_id, size_t max, char **image_ids,
+    rbd_mirror_image_status_t *images, size_t *len)
+  CEPH_RBD_DEPRECATED;
+CEPH_RBD_API void rbd_mirror_image_status_list_cleanup(
+    char **image_ids, rbd_mirror_image_status_t *images, size_t len)
+  CEPH_RBD_DEPRECATED;
+
+CEPH_RBD_API int rbd_mirror_image_status_summary(
+    rados_ioctx_t io_ctx, rbd_mirror_image_status_state_t *states, int *counts,
+    size_t *maxlen);
 
 CEPH_RBD_API int rbd_mirror_image_instance_id_list(rados_ioctx_t io_ctx,
                                                    const char *start_id,
@@ -592,7 +664,7 @@ CEPH_RBD_API int rbd_get_parent_info(rbd_image_t image,
                                     char *parent_name, size_t pnamelen,
                                     char *parent_snapname,
                                      size_t psnapnamelen)
-    __attribute__((deprecated));
+  CEPH_RBD_DEPRECATED;
 CEPH_RBD_API int rbd_get_parent_info2(rbd_image_t image,
                                       char *parent_poolname,
                                       size_t ppoolnamelen,
@@ -600,7 +672,7 @@ CEPH_RBD_API int rbd_get_parent_info2(rbd_image_t image,
                                       char *parent_id, size_t pidlen,
                                       char *parent_snapname,
                                       size_t psnapnamelen)
-    __attribute__((deprecated));
+  CEPH_RBD_DEPRECATED;
 CEPH_RBD_API int rbd_get_parent(rbd_image_t image,
                                 rbd_linked_image_spec_t *parent_image,
                                 rbd_snap_spec_t *parent_snap);
@@ -785,16 +857,16 @@ CEPH_RBD_API int rbd_sparsify_with_progress(rbd_image_t image,
 CEPH_RBD_API ssize_t rbd_list_children(rbd_image_t image, char *pools,
                                        size_t *pools_len, char *images,
                                        size_t *images_len)
-    __attribute__((deprecated));
+  CEPH_RBD_DEPRECATED;
 CEPH_RBD_API int rbd_list_children2(rbd_image_t image,
                                     rbd_child_info_t *children,
                                     int *max_children)
-    __attribute__((deprecated));
+  CEPH_RBD_DEPRECATED;
 CEPH_RBD_API void rbd_list_child_cleanup(rbd_child_info_t *child)
-    __attribute__((deprecated));
+  CEPH_RBD_DEPRECATED;
 CEPH_RBD_API void rbd_list_children_cleanup(rbd_child_info_t *children,
                                             size_t num_children)
-    __attribute__((deprecated));
+  CEPH_RBD_DEPRECATED;
 
 CEPH_RBD_API int rbd_list_children3(rbd_image_t image,
                                     rbd_linked_image_spec_t *images,
@@ -1078,9 +1150,19 @@ CEPH_RBD_API int rbd_mirror_image_resync(rbd_image_t image);
 CEPH_RBD_API int rbd_mirror_image_get_info(rbd_image_t image,
                                            rbd_mirror_image_info_t *mirror_image_info,
                                            size_t info_size);
-CEPH_RBD_API int rbd_mirror_image_get_status(rbd_image_t image,
-                                             rbd_mirror_image_status_t *mirror_image_status,
-                                             size_t status_size);
+
+CEPH_RBD_API int rbd_mirror_image_get_global_status(
+    rbd_image_t image,
+    rbd_mirror_image_global_status_t *mirror_image_global_status,
+    size_t status_size);
+CEPH_RBD_API void rbd_mirror_image_global_status_cleanup(
+    rbd_mirror_image_global_status_t *mirror_image_global_status);
+
+CEPH_RBD_API int rbd_mirror_image_get_status(
+    rbd_image_t image, rbd_mirror_image_status_t *mirror_image_status,
+    size_t status_size)
+  CEPH_RBD_DEPRECATED;
+
 CEPH_RBD_API int rbd_mirror_image_get_instance_id(rbd_image_t image,
                                                   char *instance_id,
                                                   size_t *id_max_length);
@@ -1092,10 +1174,15 @@ CEPH_RBD_API int rbd_aio_mirror_image_get_info(rbd_image_t image,
                                                rbd_mirror_image_info_t *mirror_image_info,
                                                size_t info_size,
                                                rbd_completion_t c);
-CEPH_RBD_API int rbd_aio_mirror_image_get_status(rbd_image_t image,
-                                                 rbd_mirror_image_status_t *mirror_image_status,
-                                                 size_t status_size,
-                                                 rbd_completion_t c);
+
+CEPH_RBD_API int rbd_aio_mirror_image_get_global_status(
+    rbd_image_t image,
+    rbd_mirror_image_global_status_t *mirror_global_image_status,
+    size_t status_size, rbd_completion_t c);
+CEPH_RBD_API int rbd_aio_mirror_image_get_status(
+    rbd_image_t image, rbd_mirror_image_status_t *mirror_image_status,
+    size_t status_size, rbd_completion_t c)
+  CEPH_RBD_DEPRECATED;
 
 // RBD groups support functions
 CEPH_RBD_API int rbd_group_create(rados_ioctx_t p, const char *name);
@@ -1224,8 +1311,12 @@ CEPH_RBD_API int rbd_pool_stats_option_add_uint64(rbd_pool_stats_t stats,
                                                   uint64_t* stat_val);
 CEPH_RBD_API int rbd_pool_stats_get(rados_ioctx_t io, rbd_pool_stats_t stats);
 
+#if __GNUC__ >= 4
+  #pragma GCC diagnostic pop
+#endif
+
 #ifdef __cplusplus
 }
 #endif
 
-#endif
+#endif /* CEPH_LIBRBD_H */
index 15eb9f56a31db9525c68cf4fe435a76cb1b64688..1164bf25939857084bc8d2cef377a461f5c6ca1b 100644 (file)
 #include "../rados/librados.hpp"
 #include "librbd.h"
 
+#if __GNUC__ >= 4
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
 namespace librbd {
 
   using librados::IoCtx;
@@ -80,7 +85,16 @@ namespace librbd {
     std::string uuid;
     std::string cluster_name;
     std::string client_name;
-  } mirror_peer_t;
+  } mirror_peer_t CEPH_RBD_DEPRECATED;
+
+  typedef struct {
+    std::string uuid;
+    mirror_peer_direction_t direction;
+    std::string site_name;
+    std::string fsid;
+    std::string client_name;
+    time_t last_seen;
+  } mirror_peer_site_t;
 
   typedef rbd_mirror_image_state_t mirror_image_state_t;
 
@@ -99,7 +113,21 @@ namespace librbd {
     std::string description;
     time_t last_update;
     bool up;
-  } mirror_image_status_t;
+  } mirror_image_status_t CEPH_RBD_DEPRECATED;
+
+  typedef struct {
+    std::string fsid;
+    mirror_image_status_state_t state;
+    std::string description;
+    time_t last_update;
+    bool up;
+  } mirror_image_site_status_t;
+
+  typedef struct {
+    std::string name;
+    mirror_image_info_t info;
+    std::vector<mirror_image_site_status_t> site_statuses;
+  } mirror_image_global_status_t;
 
   typedef rbd_group_image_state_t group_image_state_t;
 
@@ -214,7 +242,7 @@ public:
                                const char *snapname, RBD::AioCompletion *c);
 
   int list(IoCtx& io_ctx, std::vector<std::string>& names)
-    __attribute__((deprecated));
+    CEPH_RBD_DEPRECATED;
   int list2(IoCtx& io_ctx, std::vector<image_spec_t>* images);
 
   int create(IoCtx& io_ctx, const char *name, uint64_t size, int *order);
@@ -277,29 +305,66 @@ public:
                                    mirror_peer_direction_t direction,
                                    const std::string &token);
 
-  int mirror_peer_add(IoCtx& io_ctx, std::string *uuid,
-                      const std::string &cluster_name,
-                      const std::string &client_name);
-  int mirror_peer_remove(IoCtx& io_ctx, const std::string &uuid);
-  int mirror_peer_list(IoCtx& io_ctx, std::vector<mirror_peer_t> *peers);
-  int mirror_peer_set_client(IoCtx& io_ctx, const std::string &uuid,
-                             const std::string &client_name);
-  int mirror_peer_set_cluster(IoCtx& io_ctx, const std::string &uuid,
-                              const std::string &cluster_name);
-  int mirror_peer_get_attributes(
+  int mirror_peer_site_add(IoCtx& io_ctx, std::string *uuid,
+                           mirror_peer_direction_t direction,
+                           const std::string &site_name,
+                           const std::string &client_name);
+  int mirror_peer_site_set_name(IoCtx& io_ctx, const std::string& uuid,
+                                const std::string &site_name);
+  int mirror_peer_site_set_client_name(IoCtx& io_ctx, const std::string& uuid,
+                                       const std::string &client_name);
+  int mirror_peer_site_set_direction(IoCtx& io_ctx, const std::string& uuid,
+                                     mirror_peer_direction_t direction);
+  int mirror_peer_site_remove(IoCtx& io_ctx, const std::string& uuid);
+  int mirror_peer_site_list(IoCtx& io_ctx,
+                            std::vector<mirror_peer_site_t> *peers);
+  int mirror_peer_site_get_attributes(
       IoCtx& io_ctx, const std::string &uuid,
       std::map<std::string, std::string> *key_vals);
-  int mirror_peer_set_attributes(
+  int mirror_peer_site_set_attributes(
       IoCtx& io_ctx, const std::string &uuid,
       const std::map<std::string, std::string>& key_vals);
 
-  int mirror_image_status_list(IoCtx& io_ctx, const std::string &start_id,
-      size_t max, std::map<std::string, mirror_image_status_t> *images);
+  int mirror_image_global_status_list(
+      IoCtx& io_ctx, const std::string &start_id, size_t max,
+      std::map<std::string, mirror_image_global_status_t> *images);
   int mirror_image_status_summary(IoCtx& io_ctx,
       std::map<mirror_image_status_state_t, int> *states);
   int mirror_image_instance_id_list(IoCtx& io_ctx, const std::string &start_id,
       size_t max, std::map<std::string, std::string> *sevice_ids);
 
+  /// mirror_peer_ commands are deprecated to mirror_peer_site_ equivalents
+  int mirror_peer_add(IoCtx& io_ctx, std::string *uuid,
+                      const std::string &cluster_name,
+                      const std::string &client_name)
+    CEPH_RBD_DEPRECATED;
+  int mirror_peer_remove(IoCtx& io_ctx, const std::string &uuid)
+    CEPH_RBD_DEPRECATED;
+  int mirror_peer_list(IoCtx& io_ctx, std::vector<mirror_peer_t> *peers)
+    CEPH_RBD_DEPRECATED;
+  int mirror_peer_set_client(IoCtx& io_ctx, const std::string &uuid,
+                             const std::string &client_name)
+    CEPH_RBD_DEPRECATED;
+  int mirror_peer_set_cluster(IoCtx& io_ctx, const std::string &uuid,
+                              const std::string &cluster_name)
+    CEPH_RBD_DEPRECATED;
+  int mirror_peer_get_attributes(
+      IoCtx& io_ctx, const std::string &uuid,
+      std::map<std::string, std::string> *key_vals)
+    CEPH_RBD_DEPRECATED;
+  int mirror_peer_set_attributes(
+      IoCtx& io_ctx, const std::string &uuid,
+      const std::map<std::string, std::string>& key_vals)
+    CEPH_RBD_DEPRECATED;
+
+  /// mirror_image_status_list command is deprecated to
+  /// mirror_image_global_status_list
+
+  int mirror_image_status_list(
+      IoCtx& io_ctx, const std::string &start_id, size_t max,
+      std::map<std::string, mirror_image_status_t> *images)
+    CEPH_RBD_DEPRECATED;
+
   // RBD groups support functions
   int group_create(IoCtx& io_ctx, const char *group_name);
   int group_remove(IoCtx& io_ctx, const char *group_name);
@@ -423,10 +488,10 @@ public:
   int64_t get_data_pool_id();
   int parent_info(std::string *parent_poolname, std::string *parent_name,
                  std::string *parent_snapname)
-      __attribute__((deprecated));
+      CEPH_RBD_DEPRECATED;
   int parent_info2(std::string *parent_poolname, std::string *parent_name,
                    std::string *parent_id, std::string *parent_snapname)
-      __attribute__((deprecated));
+      CEPH_RBD_DEPRECATED;
   int get_parent(linked_image_spec_t *parent_image, snap_spec_t *parent_snap);
 
   int old_format(uint8_t *old);
@@ -489,13 +554,13 @@ public:
    * of this image at the currently set snapshot.
    */
   int list_children(std::set<std::pair<std::string, std::string> > *children)
-      __attribute__((deprecated));
+      CEPH_RBD_DEPRECATED;
   /**
   * Returns a structure of poolname, imagename, imageid and trash flag
   * for each clone of this image at the currently set snapshot.
   */
   int list_children2(std::vector<librbd::child_info_t> *children)
-      __attribute__((deprecated));
+      CEPH_RBD_DEPRECATED;
   int list_children3(std::vector<linked_image_spec_t> *images);
   int list_descendants(std::vector<linked_image_spec_t> *images);
 
@@ -510,7 +575,7 @@ public:
   /* snapshots */
   int snap_list(std::vector<snap_info_t>& snaps);
   /* DEPRECATED; use snap_exists2 */
-  bool snap_exists(const char *snapname) __attribute__ ((deprecated));
+  bool snap_exists(const char *snapname) CEPH_RBD_DEPRECATED;
   int snap_exists2(const char *snapname, bool *exists);
   int snap_create(const char *snapname);
   int snap_remove(const char *snapname);
@@ -647,15 +712,24 @@ public:
   int mirror_image_resync();
   int mirror_image_get_info(mirror_image_info_t *mirror_image_info,
                             size_t info_size);
-  int mirror_image_get_status(mirror_image_status_t *mirror_image_status,
-                             size_t status_size);
+  int mirror_image_get_global_status(
+      mirror_image_global_status_t *mirror_image_global_status,
+      size_t status_size);
+  int mirror_image_get_status(
+      mirror_image_status_t *mirror_image_status, size_t status_size)
+    CEPH_RBD_DEPRECATED;
   int mirror_image_get_instance_id(std::string *instance_id);
   int aio_mirror_image_promote(bool force, RBD::AioCompletion *c);
   int aio_mirror_image_demote(RBD::AioCompletion *c);
   int aio_mirror_image_get_info(mirror_image_info_t *mirror_image_info,
                                 size_t info_size, RBD::AioCompletion *c);
-  int aio_mirror_image_get_status(mirror_image_status_t *mirror_image_status,
-                                  size_t status_size, RBD::AioCompletion *c);
+  int aio_mirror_image_get_global_status(
+      mirror_image_global_status_t *mirror_image_global_status,
+      size_t status_size, RBD::AioCompletion *c);
+  int aio_mirror_image_get_status(
+      mirror_image_status_t *mirror_image_status, size_t status_size,
+      RBD::AioCompletion *c)
+    CEPH_RBD_DEPRECATED;
 
   int update_watch(UpdateWatchCtx *ctx, uint64_t *handle);
   int update_unwatch(uint64_t handle);
@@ -673,6 +747,10 @@ private:
   image_ctx_t ctx;
 };
 
-}
+} // namespace librbd
 
+#if __GNUC__ >= 4
+  #pragma GCC diagnostic pop
 #endif
+
+#endif // __LIBRBD_HPP
index a9c3d459165d90902c5fb1bab9a52e57c0a9bdfc..944eb150ef9f4edbe6be34b91e41bafae0f89739 100644 (file)
@@ -187,6 +187,7 @@ int create_bootstrap_user(CephContext* cct, librados::Rados& rados,
 }
 
 int create_bootstrap_peer(CephContext* cct, librados::IoCtx& io_ctx,
+                          mirror_peer_direction_t direction,
                           const std::string& site_name, const std::string& fsid,
                           const std::string& client_id, const std::string& key,
                           const std::string& mon_host,
@@ -195,31 +196,31 @@ int create_bootstrap_peer(CephContext* cct, librados::IoCtx& io_ctx,
   ldout(cct, 20) << dendl;
 
   std::string peer_uuid;
-  std::vector<mirror_peer_t> peers;
-  int r = Mirror<>::peer_list(io_ctx, &peers);
+  std::vector<mirror_peer_site_t> peers;
+  int r = Mirror<>::peer_site_list(io_ctx, &peers);
   if (r < 0 && r != -ENOENT) {
     lderr(cct) << "failed to list mirror peers: " << cpp_strerror(r) << dendl;
     return r;
   }
 
   if (peers.empty()) {
-    r = Mirror<>::peer_add(io_ctx, &peer_uuid, site_name,
-                           "client." + client_id);
+    r = Mirror<>::peer_site_add(io_ctx, &peer_uuid, direction, site_name,
+                                "client." + client_id);
     if (r < 0) {
       lderr(cct) << "failed to add " << cluster1 << " peer to "
                  << cluster2 << " " << "cluster: " << cpp_strerror(r) << dendl;
       return r;
     }
-  } else if (peers[0].cluster_name != site_name &&
-             peers[0].cluster_name != fsid) {
+  } else if (peers[0].site_name != site_name &&
+             peers[0].site_name != fsid) {
     // only support a single peer
     lderr(cct) << "multiple peers are not currently supported" << dendl;
     return -EINVAL;
   } else {
     peer_uuid = peers[0].uuid;
 
-    if (peers[0].cluster_name != site_name) {
-      r = Mirror<>::peer_set_cluster(io_ctx, peer_uuid, site_name);
+    if (peers[0].site_name != site_name) {
+      r = Mirror<>::peer_site_set_name(io_ctx, peer_uuid, site_name);
       if (r < 0) {
         // non-fatal attempt to update site name
         lderr(cct) << "failed to update peer site name" << dendl;
@@ -230,7 +231,7 @@ int create_bootstrap_peer(CephContext* cct, librados::IoCtx& io_ctx,
   Mirror<>::Attributes attributes {
     {"mon_host", mon_host},
     {"key", key}};
-  r = Mirror<>::peer_set_attributes(io_ctx, peer_uuid, attributes);
+  r = Mirror<>::peer_site_set_attributes(io_ctx, peer_uuid, attributes);
   if (r < 0) {
     lderr(cct) << "failed to update " << cluster1 << " cluster connection "
                << "attributes in " << cluster2 << " cluster: "
@@ -313,17 +314,19 @@ struct C_ImageGetInfo : public Context {
   }
 };
 
-struct C_ImageGetStatus : public C_ImageGetInfo {
+struct C_ImageGetGlobalStatus : public C_ImageGetInfo {
   std::string image_name;
-  mirror_image_status_t *mirror_image_status;
+  mirror_image_global_status_t *mirror_image_global_status;
 
   cls::rbd::MirrorImageStatus mirror_image_status_internal;
 
-  C_ImageGetStatus(const std::string &image_name,
-                   mirror_image_status_t *mirror_image_status,
-                   Context *on_finish)
-    : C_ImageGetInfo(&mirror_image_status->info, on_finish),
-      image_name(image_name), mirror_image_status(mirror_image_status) {
+  C_ImageGetGlobalStatus(
+      const std::string &image_name,
+      mirror_image_global_status_t *mirror_image_global_status,
+      Context *on_finish)
+    : C_ImageGetInfo(&mirror_image_global_status->info, on_finish),
+      image_name(image_name),
+      mirror_image_global_status(mirror_image_global_status) {
   }
 
   void finish(int r) override {
@@ -332,21 +335,18 @@ struct C_ImageGetStatus : public C_ImageGetInfo {
       return;
     }
 
-    mirror_image_status->name = image_name;
-
-    cls::rbd::MirrorImageSiteStatus local_status;
-    r = mirror_image_status_internal.get_local_mirror_image_site_status(
-      &local_status);
-    if (r < 0) {
-      on_finish->complete(r);
-      return;
+    mirror_image_global_status->name = image_name;
+    mirror_image_global_status->site_statuses.clear();
+    mirror_image_global_status->site_statuses.reserve(
+      mirror_image_status_internal.mirror_image_site_statuses.size());
+    for (auto& site_status :
+           mirror_image_status_internal.mirror_image_site_statuses) {
+      mirror_image_global_status->site_statuses.push_back({
+        site_status.fsid,
+        static_cast<mirror_image_status_state_t>(site_status.state),
+        site_status.description, site_status.last_update.sec(),
+        site_status.up});
     }
-
-    mirror_image_status->state = static_cast<mirror_image_status_state_t>(
-      local_status.state);
-    mirror_image_status->description = local_status.description;
-    mirror_image_status->last_update = local_status.last_update.sec();
-    mirror_image_status->up = local_status.up;
     C_ImageGetInfo::finish(0);
   }
 };
@@ -668,12 +668,13 @@ int Mirror<I>::image_get_info(I *ictx, mirror_image_info_t *mirror_image_info) {
 }
 
 template <typename I>
-void Mirror<I>::image_get_status(I *ictx, mirror_image_status_t *status,
-                                 Context *on_finish) {
+void Mirror<I>::image_get_global_status(I *ictx,
+                                        mirror_image_global_status_t *status,
+                                        Context *on_finish) {
   CephContext *cct = ictx->cct;
   ldout(cct, 20) << "ictx=" << ictx << dendl;
 
-  auto ctx = new C_ImageGetStatus(ictx->name, status, on_finish);
+  auto ctx = new C_ImageGetGlobalStatus(ictx->name, status, on_finish);
   auto req = mirror::GetStatusRequest<I>::create(
     *ictx, &ctx->mirror_image_status_internal, &ctx->mirror_image,
     &ctx->promotion_state, ctx);
@@ -681,9 +682,10 @@ void Mirror<I>::image_get_status(I *ictx, mirror_image_status_t *status,
 }
 
 template <typename I>
-int Mirror<I>::image_get_status(I *ictx, mirror_image_status_t *status) {
+int Mirror<I>::image_get_global_status(I *ictx,
+                                       mirror_image_global_status_t *status) {
   C_SaferCond ctx;
-  image_get_status(ictx, status, &ctx);
+  image_get_global_status(ictx, status, &ctx);
 
   int r = ctx.wait();
   if (r < 0) {
@@ -1201,18 +1203,19 @@ int Mirror<I>::peer_bootstrap_import(librados::IoCtx& io_ctx,
     std::string local_mon_host = cct->_conf.get_val<std::string>("mon_host");
 
     // create local cluster peer in remote cluster
-    r = create_bootstrap_peer(cct, remote_io_ctx, local_site_name, local_fsid,
-                              local_client_id, local_key, local_mon_host,
-                              "local", "remote");
+    r = create_bootstrap_peer(cct, remote_io_ctx,
+                              RBD_MIRROR_PEER_DIRECTION_RX_TX, local_site_name,
+                              local_fsid, local_client_id, local_key,
+                              local_mon_host, "local", "remote");
     if (r < 0) {
       return r;
     }
   }
 
   // create remote cluster peer in local cluster
-  r = create_bootstrap_peer(cct, io_ctx, remote_site_name, remote_fsid,
-                            remote_client_id, remote_key, remote_mon_host,
-                            "remote", "local");
+  r = create_bootstrap_peer(cct, io_ctx, direction, remote_site_name,
+                            remote_fsid, remote_client_id, remote_key,
+                            remote_mon_host, "remote", "local");
   if (r < 0) {
     return r;
   }
@@ -1221,18 +1224,23 @@ int Mirror<I>::peer_bootstrap_import(librados::IoCtx& io_ctx,
 }
 
 template <typename I>
-int Mirror<I>::peer_add(librados::IoCtx& io_ctx, std::string *uuid,
-                        const std::string &cluster_name,
-                        const std::string &client_name) {
+int Mirror<I>::peer_site_add(librados::IoCtx& io_ctx, std::string *uuid,
+                             mirror_peer_direction_t direction,
+                             const std::string &site_name,
+                             const std::string &client_name) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
-  ldout(cct, 20) << "name=" << cluster_name << ", "
+  ldout(cct, 20) << "name=" << site_name << ", "
                  << "client=" << client_name << dendl;
 
-  if (cct->_conf->cluster == cluster_name) {
+  if (cct->_conf->cluster == site_name) {
     lderr(cct) << "cannot add self as remote peer" << dendl;
     return -EINVAL;
   }
 
+  if (direction == RBD_MIRROR_PEER_DIRECTION_TX) {
+    return -EINVAL;
+  }
+
   int r;
   do {
     uuid_d uuid_gen;
@@ -1240,9 +1248,8 @@ int Mirror<I>::peer_add(librados::IoCtx& io_ctx, std::string *uuid,
 
     *uuid = uuid_gen.to_string();
     r = cls_client::mirror_peer_add(
-      &io_ctx,
-      {*uuid, cls::rbd::MIRROR_PEER_DIRECTION_RX, cluster_name, client_name,
-       ""});
+      &io_ctx, {*uuid, static_cast<cls::rbd::MirrorPeerDirection>(direction),
+                site_name, client_name, ""});
     if (r == -ESTALE) {
       ldout(cct, 5) << "duplicate UUID detected, retrying" << dendl;
     } else if (r < 0) {
@@ -1255,7 +1262,8 @@ int Mirror<I>::peer_add(librados::IoCtx& io_ctx, std::string *uuid,
 }
 
 template <typename I>
-int Mirror<I>::peer_remove(librados::IoCtx& io_ctx, const std::string &uuid) {
+int Mirror<I>::peer_site_remove(librados::IoCtx& io_ctx,
+                                const std::string &uuid) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
   ldout(cct, 20) << "uuid=" << uuid << dendl;
 
@@ -1276,8 +1284,8 @@ int Mirror<I>::peer_remove(librados::IoCtx& io_ctx, const std::string &uuid) {
 }
 
 template <typename I>
-int Mirror<I>::peer_list(librados::IoCtx& io_ctx,
-                         std::vector<mirror_peer_t> *peers) {
+int Mirror<I>::peer_site_list(librados::IoCtx& io_ctx,
+                              std::vector<mirror_peer_site_t> *peers) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
   ldout(cct, 20) << dendl;
 
@@ -1291,18 +1299,23 @@ int Mirror<I>::peer_list(librados::IoCtx& io_ctx,
   peers->clear();
   peers->reserve(mirror_peers.size());
   for (auto &mirror_peer : mirror_peers) {
-    mirror_peer_t peer;
+    mirror_peer_site_t peer;
     peer.uuid = mirror_peer.uuid;
-    peer.cluster_name = mirror_peer.site_name;
+    peer.direction = static_cast<mirror_peer_direction_t>(
+      mirror_peer.mirror_peer_direction);
+    peer.site_name = mirror_peer.site_name;
+    peer.fsid = mirror_peer.fsid;
     peer.client_name = mirror_peer.client_name;
+    peer.last_seen = mirror_peer.last_seen.sec();
     peers->push_back(peer);
   }
   return 0;
 }
 
 template <typename I>
-int Mirror<I>::peer_set_client(librados::IoCtx& io_ctx, const std::string &uuid,
-                               const std::string &client_name) {
+int Mirror<I>::peer_site_set_client(librados::IoCtx& io_ctx,
+                                    const std::string &uuid,
+                                    const std::string &client_name) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
   ldout(cct, 20) << "uuid=" << uuid << ", "
                  << "client=" << client_name << dendl;
@@ -1317,21 +1330,21 @@ int Mirror<I>::peer_set_client(librados::IoCtx& io_ctx, const std::string &uuid,
 }
 
 template <typename I>
-int Mirror<I>::peer_set_cluster(librados::IoCtx& io_ctx,
-                                const std::string &uuid,
-                                const std::string &cluster_name) {
+int Mirror<I>::peer_site_set_name(librados::IoCtx& io_ctx,
+                                  const std::string &uuid,
+                                  const std::string &site_name) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
   ldout(cct, 20) << "uuid=" << uuid << ", "
-                 << "cluster=" << cluster_name << dendl;
+                 << "name=" << site_name << dendl;
 
-  if (cct->_conf->cluster == cluster_name) {
+  if (cct->_conf->cluster == site_name) {
     lderr(cct) << "cannot set self as remote peer" << dendl;
     return -EINVAL;
   }
 
-  int r = cls_client::mirror_peer_set_cluster(&io_ctx, uuid, cluster_name);
+  int r = cls_client::mirror_peer_set_cluster(&io_ctx, uuid, site_name);
   if (r < 0) {
-    lderr(cct) << "failed to update cluster '" << uuid << "': "
+    lderr(cct) << "failed to update site '" << uuid << "': "
                << cpp_strerror(r) << dendl;
     return r;
   }
@@ -1339,9 +1352,30 @@ int Mirror<I>::peer_set_cluster(librados::IoCtx& io_ctx,
 }
 
 template <typename I>
-int Mirror<I>::peer_get_attributes(librados::IoCtx& io_ctx,
-                                   const std::string &uuid,
-                                   Attributes* attributes) {
+int Mirror<I>::peer_site_set_direction(librados::IoCtx& io_ctx,
+                                       const std::string &uuid,
+                                       mirror_peer_direction_t direction) {
+  cls::rbd::MirrorPeerDirection mirror_peer_direction = static_cast<
+    cls::rbd::MirrorPeerDirection>(direction);
+
+  CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
+  ldout(cct, 20) << "uuid=" << uuid << ", "
+                 << "direction=" << mirror_peer_direction << dendl;
+
+  int r = cls_client::mirror_peer_set_direction(&io_ctx, uuid,
+                                                mirror_peer_direction);
+  if (r < 0) {
+    lderr(cct) << "failed to update direction '" << uuid << "': "
+               << cpp_strerror(r) << dendl;
+    return r;
+  }
+  return 0;
+}
+
+template <typename I>
+int Mirror<I>::peer_site_get_attributes(librados::IoCtx& io_ctx,
+                                        const std::string &uuid,
+                                        Attributes* attributes) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
   ldout(cct, 20) << "uuid=" << uuid << dendl;
 
@@ -1380,21 +1414,21 @@ int Mirror<I>::peer_get_attributes(librados::IoCtx& io_ctx,
 }
 
 template <typename I>
-int Mirror<I>::peer_set_attributes(librados::IoCtx& io_ctx,
-                                   const std::string &uuid,
-                                   const Attributes& attributes) {
+int Mirror<I>::peer_site_set_attributes(librados::IoCtx& io_ctx,
+                                        const std::string &uuid,
+                                        const Attributes& attributes) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
   ldout(cct, 20) << "uuid=" << uuid << ", "
                  << "attributes=" << attributes << dendl;
 
-  std::vector<mirror_peer_t> mirror_peers;
-  int r = peer_list(io_ctx, &mirror_peers);
+  std::vector<mirror_peer_site_t> mirror_peers;
+  int r = peer_site_list(io_ctx, &mirror_peers);
   if (r < 0) {
     return r;
   }
 
   if (std::find_if(mirror_peers.begin(), mirror_peers.end(),
-                   [&uuid](const librbd::mirror_peer_t& peer) {
+                   [&uuid](const librbd::mirror_peer_site_t& peer) {
                      return uuid == peer.uuid;
                    }) == mirror_peers.end()) {
     ldout(cct, 5) << "mirror peer uuid " << uuid << " does not exist" << dendl;
@@ -1425,9 +1459,9 @@ int Mirror<I>::peer_set_attributes(librados::IoCtx& io_ctx,
 }
 
 template <typename I>
-int Mirror<I>::image_status_list(librados::IoCtx& io_ctx,
-                                  const std::string &start_id, size_t max,
-                                  IdToMirrorImageStatus *images) {
+int Mirror<I>::image_global_status_list(
+    librados::IoCtx& io_ctx, const std::string &start_id, size_t max,
+    IdToMirrorImageGlobalStatus *images) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
   int r;
 
@@ -1454,10 +1488,7 @@ int Mirror<I>::image_status_list(librados::IoCtx& io_ctx,
     return r;
   }
 
-  cls::rbd::MirrorImageSiteStatus unknown_status(
-    cls::rbd::MirrorImageSiteStatus::LOCAL_FSID,
-    cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN, "status not found");
-
+  const std::string STATUS_NOT_FOUND("status not found");
   for (auto it = images_.begin(); it != images_.end(); ++it) {
     auto &image_id = it->first;
     auto &info = it->second;
@@ -1472,22 +1503,33 @@ int Mirror<I>::image_status_list(librados::IoCtx& io_ctx,
       image_name = image_id;
     }
 
-    auto s = unknown_status;
+    mirror_image_global_status_t& global_status = (*images)[image_id];
+    global_status.name = image_name;
+    global_status.info = mirror_image_info_t{
+        info.global_image_id,
+        static_cast<mirror_image_state_t>(info.state),
+        false}; // XXX: To set "primary" right would require an additional call.
+
     auto s_it = statuses_.find(image_id);
     if (s_it != statuses_.end()) {
-      s_it->second.get_local_mirror_image_site_status(&s);
+      auto& status = s_it->second;
+
+      global_status.site_statuses.reserve(
+        status.mirror_image_site_statuses.size());
+      for (auto& site_status : status.mirror_image_site_statuses) {
+        global_status.site_statuses.push_back(mirror_image_site_status_t{
+          site_status.fsid,
+          static_cast<mirror_image_status_state_t>(site_status.state),
+          site_status.state == cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN ?
+            STATUS_NOT_FOUND : site_status.description,
+          site_status.last_update.sec(), site_status.up});
+      }
+    } else {
+      // older OSD that only returns local status
+      global_status.site_statuses.push_back(mirror_image_site_status_t{
+        cls::rbd::MirrorImageSiteStatus::LOCAL_FSID,
+        MIRROR_IMAGE_STATUS_STATE_UNKNOWN, STATUS_NOT_FOUND, 0, false});
     }
-
-    (*images)[image_id] = mirror_image_status_t{
-      image_name,
-      mirror_image_info_t{
-        info.global_image_id,
-        static_cast<mirror_image_state_t>(info.state),
-        false}, // XXX: To set "primary" right would require an additional call.
-      static_cast<mirror_image_status_state_t>(s.state),
-      s.description,
-      s.last_update.sec(),
-      s.up};
   }
 
   return 0;
@@ -1498,8 +1540,16 @@ int Mirror<I>::image_status_summary(librados::IoCtx& io_ctx,
                                     MirrorImageStatusStates *states) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
 
+  std::vector<cls::rbd::MirrorPeer> mirror_peers;
+  int r = cls_client::mirror_peer_list(&io_ctx, &mirror_peers);
+  if (r < 0 && r != -ENOENT) {
+    lderr(cct) << "failed to list mirror peers: " << cpp_strerror(r) << dendl;
+    return r;
+  }
+
   std::map<cls::rbd::MirrorImageStatusState, int> states_;
-  int r = cls_client::mirror_image_status_get_summary(&io_ctx, {}, &states_);
+  r = cls_client::mirror_image_status_get_summary(&io_ctx, mirror_peers,
+                                                  &states_);
   if (r < 0 && r != -ENOENT) {
     lderr(cct) << "failed to get mirror status summary: "
                << cpp_strerror(r) << dendl;
index 94768acdbbd66999bb776e872cf63151a58b7c0a..c7d10662e5fc1ad890b85ac10d633f0eaa7d1b3d 100644 (file)
@@ -20,7 +20,8 @@ namespace api {
 template <typename ImageCtxT = librbd::ImageCtx>
 struct Mirror {
   typedef std::map<std::string, std::string> Attributes;
-  typedef std::map<std::string, mirror_image_status_t> IdToMirrorImageStatus;
+  typedef std::map<std::string, mirror_image_global_status_t>
+    IdToMirrorImageGlobalStatus;
   typedef std::map<mirror_image_status_state_t, int> MirrorImageStatusStates;
 
   static int site_name_get(librados::Rados& rados, std::string* name);
@@ -34,26 +35,33 @@ struct Mirror {
                                    rbd_mirror_peer_direction_t direction,
                                    const std::string& token);
 
-  static int peer_add(librados::IoCtx& io_ctx, std::string *uuid,
-                      const std::string &cluster_name,
-                      const std::string &client_name);
-  static int peer_remove(librados::IoCtx& io_ctx, const std::string &uuid);
-  static int peer_list(librados::IoCtx& io_ctx,
-                       std::vector<mirror_peer_t> *peers);
-  static int peer_set_client(librados::IoCtx& io_ctx, const std::string &uuid,
-                             const std::string &client_name);
-  static int peer_set_cluster(librados::IoCtx& io_ctx, const std::string &uuid,
-                              const std::string &cluster_name);
-  static int peer_get_attributes(librados::IoCtx& io_ctx,
-                                 const std::string &uuid,
-                                 Attributes* attributes);
-  static int peer_set_attributes(librados::IoCtx& io_ctx,
-                                 const std::string &uuid,
-                                 const Attributes& attributes);
-
-  static int image_status_list(librados::IoCtx& io_ctx,
-                               const std::string &start_id, size_t max,
-                               IdToMirrorImageStatus *images);
+  static int peer_site_add(librados::IoCtx& io_ctx, std::string *uuid,
+                           mirror_peer_direction_t direction,
+                           const std::string &site_name,
+                           const std::string &client_name);
+  static int peer_site_remove(librados::IoCtx& io_ctx, const std::string &uuid);
+  static int peer_site_list(librados::IoCtx& io_ctx,
+                            std::vector<mirror_peer_site_t> *peers);
+  static int peer_site_set_client(librados::IoCtx& io_ctx,
+                                  const std::string &uuid,
+                                  const std::string &client_name);
+  static int peer_site_set_name(librados::IoCtx& io_ctx,
+                                const std::string &uuid,
+                                const std::string &site_name);
+  static int peer_site_set_direction(librados::IoCtx& io_ctx,
+                                     const std::string &uuid,
+                                     mirror_peer_direction_t direction);
+  static int peer_site_get_attributes(librados::IoCtx& io_ctx,
+                                      const std::string &uuid,
+                                      Attributes* attributes);
+  static int peer_site_set_attributes(librados::IoCtx& io_ctx,
+                                      const std::string &uuid,
+                                      const Attributes& attributes);
+
+  static int image_global_status_list(librados::IoCtx& io_ctx,
+                                      const std::string &start_id, size_t max,
+                                      IdToMirrorImageGlobalStatus *images);
+
   static int image_status_summary(librados::IoCtx& io_ctx,
                                   MirrorImageStatusStates *states);
   static int image_instance_id_list(librados::IoCtx& io_ctx,
@@ -73,9 +81,11 @@ struct Mirror {
   static void image_get_info(ImageCtxT *ictx,
                              mirror_image_info_t *mirror_image_info,
                              Context *on_finish);
-  static int image_get_status(ImageCtxT *ictx, mirror_image_status_t *status);
-  static void image_get_status(ImageCtxT *ictx, mirror_image_status_t *status,
-                               Context *on_finish);
+  static int image_get_global_status(ImageCtxT *ictx,
+                                     mirror_image_global_status_t *status);
+  static void image_get_global_status(ImageCtxT *ictx,
+                                      mirror_image_global_status_t *status,
+                                      Context *on_finish);
   static int image_get_instance_id(ImageCtxT *ictx, std::string *instance_id);
 };
 
index bd8a58e86c19152999037c376d21a7492a506e89..9aa5d2f989965ef8bd671304f149bf2efd10ac0b 100644 (file)
@@ -212,14 +212,66 @@ void mirror_image_info_cpp_to_c(const librbd::mirror_image_info_t &cpp_info,
   c_info->primary = cpp_info.primary;
 }
 
-void mirror_image_status_cpp_to_c(const librbd::mirror_image_status_t &cpp_status,
-                                 rbd_mirror_image_status_t *c_status) {
+int get_local_mirror_image_site_status(
+    const librbd::mirror_image_global_status_t& status,
+    librbd::mirror_image_site_status_t* local_status) {
+  auto it = std::find_if(status.site_statuses.begin(),
+                         status.site_statuses.end(),
+                         [](const librbd::mirror_image_site_status_t& s) {
+      return (s.fsid == cls::rbd::MirrorImageSiteStatus::LOCAL_FSID);
+    });
+  if (it == status.site_statuses.end()) {
+    return -ENOENT;
+  }
+
+  *local_status = *it;
+  return 0;
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+int mirror_image_global_status_cpp_to_c(
+    const librbd::mirror_image_global_status_t &cpp_status,
+    rbd_mirror_image_status_t *c_status) {
+  c_status->name = strdup(cpp_status.name.c_str());
+  mirror_image_info_cpp_to_c(cpp_status.info, &c_status->info);
+
+  librbd::mirror_image_site_status_t local_status;
+  int r = get_local_mirror_image_site_status(cpp_status, &local_status);
+  if (r < 0) {
+    return r;
+  }
+
+  c_status->state = local_status.state;
+  c_status->description = strdup(local_status.description.c_str());
+  c_status->last_update = local_status.last_update;
+  c_status->up = local_status.up;
+  return 0;
+}
+
+#pragma GCC diagnostic pop
+
+void mirror_image_global_status_cpp_to_c(
+    const librbd::mirror_image_global_status_t &cpp_status,
+    rbd_mirror_image_global_status_t *c_status) {
   c_status->name = strdup(cpp_status.name.c_str());
   mirror_image_info_cpp_to_c(cpp_status.info, &c_status->info);
-  c_status->state = cpp_status.state;
-  c_status->description = strdup(cpp_status.description.c_str());
-  c_status->last_update = cpp_status.last_update;
-  c_status->up = cpp_status.up;
+
+  c_status->site_statuses_count = cpp_status.site_statuses.size();
+  c_status->site_statuses = (rbd_mirror_image_site_status_t*)calloc(
+    cpp_status.site_statuses.size(), sizeof(rbd_mirror_image_site_status_t));
+
+  auto idx = 0U;
+  for (auto it = cpp_status.site_statuses.begin();
+       it != cpp_status.site_statuses.end(); ++it) {
+    auto& s_status = c_status->site_statuses[idx++];
+    s_status.fsid = strdup(it->fsid.c_str());
+    s_status.state = it->state;
+    s_status.description = strdup(it->description.c_str());
+    s_status.last_update = it->last_update;
+    s_status.up = it->up;
+  }
 }
 
 void trash_image_info_cpp_to_c(const librbd::trash_image_info_t &cpp_info,
@@ -265,16 +317,50 @@ struct C_MirrorImageGetInfo : public Context {
   }
 };
 
+struct C_MirrorImageGetGlobalStatus : public Context {
+  rbd_mirror_image_global_status_t *mirror_image_global_status;
+  Context *on_finish;
+
+  librbd::mirror_image_global_status_t cpp_mirror_image_global_status;
+
+  C_MirrorImageGetGlobalStatus(
+      rbd_mirror_image_global_status_t *mirror_image_global_status,
+      Context *on_finish)
+    : mirror_image_global_status(mirror_image_global_status),
+      on_finish(on_finish) {
+  }
+
+  void finish(int r) override {
+    if (r < 0) {
+      on_finish->complete(r);
+      return;
+    }
+
+    mirror_image_global_status_cpp_to_c(cpp_mirror_image_global_status,
+                                        mirror_image_global_status);
+    on_finish->complete(0);
+  }
+};
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
 struct C_MirrorImageGetStatus : public Context {
-  rbd_mirror_image_status_t *mirror_image_status;
+  librbd::mirror_image_status_t *mirror_image_status_cpp = nullptr;
+  rbd_mirror_image_status_t *mirror_image_status = nullptr;
   Context *on_finish;
 
-  librbd::mirror_image_status_t cpp_mirror_image_status;
+  librbd::mirror_image_global_status_t cpp_mirror_image_global_status;
 
   C_MirrorImageGetStatus(rbd_mirror_image_status_t *mirror_image_status,
                          Context *on_finish)
     : mirror_image_status(mirror_image_status), on_finish(on_finish) {
   }
+  C_MirrorImageGetStatus(librbd::mirror_image_status_t *mirror_image_status,
+                         Context *on_finish)
+    : mirror_image_status_cpp(mirror_image_status), on_finish(on_finish) {
+  }
+
 
   void finish(int r) override {
     if (r < 0) {
@@ -282,11 +368,27 @@ struct C_MirrorImageGetStatus : public Context {
       return;
     }
 
-    mirror_image_status_cpp_to_c(cpp_mirror_image_status, mirror_image_status);
-    on_finish->complete(0);
+    if (mirror_image_status != nullptr) {
+      r = mirror_image_global_status_cpp_to_c(cpp_mirror_image_global_status,
+                                              mirror_image_status);
+    } else if (mirror_image_status_cpp != nullptr) {
+      librbd::mirror_image_site_status_t local_status;
+      r = get_local_mirror_image_site_status(cpp_mirror_image_global_status,
+                                             &local_status);
+      if (r >= 0) {
+        *mirror_image_status_cpp = {
+          cpp_mirror_image_global_status.name,
+          cpp_mirror_image_global_status.info,
+          local_status.state, local_status.description,
+          local_status.last_update, local_status.up};
+      }
+    }
+    on_finish->complete(r);
   }
 };
 
+#pragma GCC diagnostic pop
+
 } // anonymous namespace
 
 namespace librbd {
@@ -893,49 +995,148 @@ namespace librbd {
                                                         token);
   }
 
+  int RBD::mirror_peer_site_add(IoCtx& io_ctx, std::string *uuid,
+                                mirror_peer_direction_t direction,
+                                const std::string &site_name,
+                                const std::string &client_name) {
+    return librbd::api::Mirror<>::peer_site_add(
+      io_ctx, uuid, direction, site_name, client_name);
+  }
+
+  int RBD::mirror_peer_site_remove(IoCtx& io_ctx, const std::string &uuid) {
+    return librbd::api::Mirror<>::peer_site_remove(io_ctx, uuid);
+  }
+
+  int RBD::mirror_peer_site_list(
+      IoCtx& io_ctx, std::vector<mirror_peer_site_t> *peer_sites) {
+    return librbd::api::Mirror<>::peer_site_list(io_ctx, peer_sites);
+  }
+
+  int RBD::mirror_peer_site_set_client_name(
+      IoCtx& io_ctx, const std::string &uuid, const std::string &client_name) {
+    return librbd::api::Mirror<>::peer_site_set_client(io_ctx, uuid,
+                                                       client_name);
+  }
+
+  int RBD::mirror_peer_site_set_name(IoCtx& io_ctx, const std::string &uuid,
+                                     const std::string &site_name) {
+    return librbd::api::Mirror<>::peer_site_set_name(io_ctx, uuid,
+                                                     site_name);
+  }
+
+  int RBD::mirror_peer_site_set_direction(IoCtx& io_ctx,
+                                          const std::string& uuid,
+                                          mirror_peer_direction_t direction) {
+    return librbd::api::Mirror<>::peer_site_set_direction(io_ctx, uuid,
+                                                          direction);
+  }
+
+  int RBD::mirror_peer_site_get_attributes(
+      IoCtx& io_ctx, const std::string &uuid,
+      std::map<std::string, std::string> *key_vals) {
+    return librbd::api::Mirror<>::peer_site_get_attributes(io_ctx, uuid,
+                                                           key_vals);
+  }
+
+  int RBD::mirror_peer_site_set_attributes(
+      IoCtx& io_ctx, const std::string &uuid,
+      const std::map<std::string, std::string>& key_vals) {
+    return librbd::api::Mirror<>::peer_site_set_attributes(io_ctx, uuid,
+                                                           key_vals);
+  }
+
+  int RBD::mirror_image_global_status_list(
+      IoCtx& io_ctx, const std::string &start_id, size_t max,
+      std::map<std::string, mirror_image_global_status_t> *global_statuses) {
+    return librbd::api::Mirror<>::image_global_status_list(
+      io_ctx, start_id, max, global_statuses);
+  }
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
   int RBD::mirror_peer_add(IoCtx& io_ctx, std::string *uuid,
                            const std::string &cluster_name,
                            const std::string &client_name) {
-    return librbd::api::Mirror<>::peer_add(io_ctx, uuid, cluster_name,
-                                           client_name);
+    return librbd::api::Mirror<>::peer_site_add(
+      io_ctx, uuid, RBD_MIRROR_PEER_DIRECTION_RX_TX, cluster_name, client_name);
   }
 
   int RBD::mirror_peer_remove(IoCtx& io_ctx, const std::string &uuid) {
-    return librbd::api::Mirror<>::peer_remove(io_ctx, uuid);
+    return librbd::api::Mirror<>::peer_site_remove(io_ctx, uuid);
   }
 
   int RBD::mirror_peer_list(IoCtx& io_ctx, std::vector<mirror_peer_t> *peers) {
-    return librbd::api::Mirror<>::peer_list(io_ctx, peers);
+    std::vector<mirror_peer_site_t> peer_sites;
+    int r = librbd::api::Mirror<>::peer_site_list(io_ctx, &peer_sites);
+    if (r < 0) {
+      return r;
+    }
+
+    peers->clear();
+    peers->reserve(peer_sites.size());
+    for (auto& peer_site : peer_sites) {
+      peers->push_back({peer_site.uuid, peer_site.site_name,
+                        peer_site.client_name});
+    }
+    return 0;
   }
 
   int RBD::mirror_peer_set_client(IoCtx& io_ctx, const std::string &uuid,
                                   const std::string &client_name) {
-    return librbd::api::Mirror<>::peer_set_client(io_ctx, uuid, client_name);
+    return librbd::api::Mirror<>::peer_site_set_client(io_ctx, uuid,
+                                                       client_name);
   }
 
   int RBD::mirror_peer_set_cluster(IoCtx& io_ctx, const std::string &uuid,
                                    const std::string &cluster_name) {
-    return librbd::api::Mirror<>::peer_set_cluster(io_ctx, uuid, cluster_name);
+    return librbd::api::Mirror<>::peer_site_set_name(io_ctx, uuid,
+                                                     cluster_name);
   }
 
   int RBD::mirror_peer_get_attributes(
       IoCtx& io_ctx, const std::string &uuid,
       std::map<std::string, std::string> *key_vals) {
-    return librbd::api::Mirror<>::peer_get_attributes(io_ctx, uuid, key_vals);
+    return librbd::api::Mirror<>::peer_site_get_attributes(io_ctx, uuid,
+                                                           key_vals);
   }
 
   int RBD::mirror_peer_set_attributes(
       IoCtx& io_ctx, const std::string &uuid,
       const std::map<std::string, std::string>& key_vals) {
-    return librbd::api::Mirror<>::peer_set_attributes(io_ctx, uuid, key_vals);
+    return librbd::api::Mirror<>::peer_site_set_attributes(io_ctx, uuid,
+                                                           key_vals);
   }
 
   int RBD::mirror_image_status_list(IoCtx& io_ctx, const std::string &start_id,
       size_t max, std::map<std::string, mirror_image_status_t> *images) {
-    return librbd::api::Mirror<>::image_status_list(io_ctx, start_id, max,
-                                                    images);
+    std::map<std::string, mirror_image_global_status_t> global_statuses;
+
+    int r = librbd::api::Mirror<>::image_global_status_list(
+      io_ctx, start_id, max, &global_statuses);
+    if (r < 0) {
+      return r;
+    }
+
+    images->clear();
+    for (auto &[id, global_status] : global_statuses) {
+      if (global_status.site_statuses.empty() ||
+          global_status.site_statuses[0].fsid !=
+            cls::rbd::MirrorImageSiteStatus::LOCAL_FSID) {
+        continue;
+      }
+
+      auto& site_status = global_status.site_statuses[0];
+      (*images)[id] = mirror_image_status_t{
+        global_status.name, global_status.info, site_status.state,
+        site_status.description, site_status.last_update, site_status.up};
+    }
+
+    return 0;
   }
 
+#pragma GCC diagnostic pop
+
   int RBD::mirror_image_status_summary(IoCtx& io_ctx,
       std::map<mirror_image_status_state_t, int> *states) {
     return librbd::api::Mirror<>::image_status_summary(io_ctx, states);
@@ -2557,6 +2758,22 @@ namespace librbd {
     return librbd::api::Mirror<>::image_get_info(ictx, mirror_image_info);
   }
 
+  int Image::mirror_image_get_global_status(
+      mirror_image_global_status_t *mirror_image_global_status,
+      size_t status_size) {
+    ImageCtx *ictx = (ImageCtx *)ctx;
+
+    if (sizeof(mirror_image_global_status_t) != status_size) {
+      return -ERANGE;
+    }
+
+    return librbd::api::Mirror<>::image_get_global_status(
+      ictx, mirror_image_global_status);
+  }
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
   int Image::mirror_image_get_status(mirror_image_status_t *mirror_image_status,
                                     size_t status_size) {
     ImageCtx *ictx = (ImageCtx *)ctx;
@@ -2565,9 +2782,29 @@ namespace librbd {
       return -ERANGE;
     }
 
-    return librbd::api::Mirror<>::image_get_status(ictx, mirror_image_status);
+    mirror_image_global_status_t mirror_image_global_status;
+    int r = librbd::api::Mirror<>::image_get_global_status(
+      ictx, &mirror_image_global_status);
+    if (r < 0) {
+      return r;
+    }
+
+    librbd::mirror_image_site_status_t local_status;
+    r = get_local_mirror_image_site_status(mirror_image_global_status,
+                                           &local_status);
+    if (r < 0) {
+      return r;
+    }
+
+    *mirror_image_status = mirror_image_status_t{
+      mirror_image_global_status.name, mirror_image_global_status.info,
+      local_status.state, local_status.description, local_status.last_update,
+      local_status.up};
+    return 0;
   }
 
+#pragma GCC diagnostic pop
+
   int Image::mirror_image_get_instance_id(std::string *instance_id) {
     ImageCtx *ictx = (ImageCtx *)ctx;
 
@@ -2606,6 +2843,24 @@ namespace librbd {
     return 0;
   }
 
+  int Image::aio_mirror_image_get_global_status(
+      mirror_image_global_status_t *status, size_t status_size,
+      RBD::AioCompletion *c) {
+    ImageCtx *ictx = (ImageCtx *)ctx;
+
+    if (sizeof(mirror_image_global_status_t) != status_size) {
+      return -ERANGE;
+    }
+
+    librbd::api::Mirror<>::image_get_global_status(
+      ictx, status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
+                                        get_aio_completion(c)));
+    return 0;
+  }
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
   int Image::aio_mirror_image_get_status(mirror_image_status_t *status,
                                          size_t status_size,
                                          RBD::AioCompletion *c) {
@@ -2615,12 +2870,16 @@ namespace librbd {
       return -ERANGE;
     }
 
-    librbd::api::Mirror<>::image_get_status(
-      ictx, status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
-                                        get_aio_completion(c)));
+    auto ctx = new C_MirrorImageGetStatus(
+      status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
+                                  get_aio_completion(c)));
+    librbd::api::Mirror<>::image_get_global_status(
+      ictx, &ctx->cpp_mirror_image_global_status, ctx);
     return 0;
   }
 
+#pragma GCC diagnostic pop
+
   int Image::update_watch(UpdateWatchCtx *wctx, uint64_t *handle) {
     ImageCtx *ictx = (ImageCtx *)ctx;
     tracepoint(librbd, update_watch_enter, ictx, wctx);
@@ -2812,10 +3071,11 @@ extern "C" int rbd_mirror_peer_bootstrap_import(
   return librbd::api::Mirror<>::peer_bootstrap_import(io_ctx, direction, token);
 }
 
-extern "C" int rbd_mirror_peer_add(rados_ioctx_t p, char *uuid,
-                                   size_t uuid_max_length,
-                                   const char *cluster_name,
-                                   const char *client_name) {
+extern "C" int rbd_mirror_peer_site_add(rados_ioctx_t p, char *uuid,
+                                        size_t uuid_max_length,
+                                        rbd_mirror_peer_direction_t direction,
+                                        const char *site_name,
+                                        const char *client_name) {
   static const std::size_t UUID_LENGTH = 36;
 
   librados::IoCtx io_ctx;
@@ -2826,8 +3086,8 @@ extern "C" int rbd_mirror_peer_add(rados_ioctx_t p, char *uuid,
   }
 
   std::string uuid_str;
-  int r = librbd::api::Mirror<>::peer_add(io_ctx, &uuid_str, cluster_name,
-                                          client_name);
+  int r = librbd::api::Mirror<>::peer_site_add(io_ctx, &uuid_str, direction,
+                                               site_name, client_name);
   if (r >= 0) {
     strncpy(uuid, uuid_str.c_str(), uuid_max_length);
     uuid[uuid_max_length - 1] = '\0';
@@ -2835,20 +3095,20 @@ extern "C" int rbd_mirror_peer_add(rados_ioctx_t p, char *uuid,
   return r;
 }
 
-extern "C" int rbd_mirror_peer_remove(rados_ioctx_t p, const char *uuid) {
+extern "C" int rbd_mirror_peer_site_remove(rados_ioctx_t p, const char *uuid) {
   librados::IoCtx io_ctx;
   librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
-  int r = librbd::api::Mirror<>::peer_remove(io_ctx, uuid);
+  int r = librbd::api::Mirror<>::peer_site_remove(io_ctx, uuid);
   return r;
 }
 
-extern "C" int rbd_mirror_peer_list(rados_ioctx_t p,
-                                    rbd_mirror_peer_t *peers, int *max_peers) {
+extern "C" int rbd_mirror_peer_site_list(
+    rados_ioctx_t p, rbd_mirror_peer_site_t *peers, int *max_peers) {
   librados::IoCtx io_ctx;
   librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
 
-  std::vector<librbd::mirror_peer_t> peer_vector;
-  int r = librbd::api::Mirror<>::peer_list(io_ctx, &peer_vector);
+  std::vector<librbd::mirror_peer_site_t> peer_vector;
+  int r = librbd::api::Mirror<>::peer_site_list(io_ctx, &peer_vector);
   if (r < 0) {
     return r;
   }
@@ -2860,44 +3120,56 @@ extern "C" int rbd_mirror_peer_list(rados_ioctx_t p,
 
   for (int i = 0; i < static_cast<int>(peer_vector.size()); ++i) {
     peers[i].uuid = strdup(peer_vector[i].uuid.c_str());
-    peers[i].cluster_name = strdup(peer_vector[i].cluster_name.c_str());
+    peers[i].direction = peer_vector[i].direction;
+    peers[i].site_name = strdup(peer_vector[i].site_name.c_str());
+    peers[i].fsid = strdup(peer_vector[i].fsid.c_str());
     peers[i].client_name = strdup(peer_vector[i].client_name.c_str());
   }
   *max_peers = static_cast<int>(peer_vector.size());
   return 0;
 }
 
-extern "C" void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers,
-                                             int max_peers) {
+extern "C" void rbd_mirror_peer_site_list_cleanup(rbd_mirror_peer_site_t *peers,
+                                                  int max_peers) {
   for (int i = 0; i < max_peers; ++i) {
     free(peers[i].uuid);
-    free(peers[i].cluster_name);
+    free(peers[i].site_name);
+    free(peers[i].fsid);
     free(peers[i].client_name);
   }
 }
 
-extern "C" int rbd_mirror_peer_set_client(rados_ioctx_t p, const char *uuid,
-                                          const char *client_name) {
+extern "C" int rbd_mirror_peer_site_set_client_name(
+    rados_ioctx_t p, const char *uuid, const char *client_name) {
   librados::IoCtx io_ctx;
   librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
-  return librbd::api::Mirror<>::peer_set_client(io_ctx, uuid, client_name);
+  return librbd::api::Mirror<>::peer_site_set_client(io_ctx, uuid, client_name);
 }
 
-extern "C" int rbd_mirror_peer_set_cluster(rados_ioctx_t p, const char *uuid,
-                                           const char *cluster_name) {
+extern "C" int rbd_mirror_peer_site_set_name(
+    rados_ioctx_t p, const char *uuid, const char *site_name) {
   librados::IoCtx io_ctx;
   librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
-  return librbd::api::Mirror<>::peer_set_cluster(io_ctx, uuid, cluster_name);
+  return librbd::api::Mirror<>::peer_site_set_name(io_ctx, uuid, site_name);
 }
 
-extern "C" int rbd_mirror_peer_get_attributes(
+extern "C" int rbd_mirror_peer_site_set_direction(
+    rados_ioctx_t p, const char *uuid, rbd_mirror_peer_direction_t direction) {
+  librados::IoCtx io_ctx;
+  librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
+  return librbd::api::Mirror<>::peer_site_set_direction(io_ctx, uuid,
+                                                        direction);
+}
+
+extern "C" int rbd_mirror_peer_site_get_attributes(
     rados_ioctx_t p, const char *uuid, char *keys, size_t *max_key_len,
     char *values, size_t *max_val_len, size_t *key_value_count) {
   librados::IoCtx io_ctx;
   librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
 
   std::map<std::string, std::string> attributes;
-  int r = librbd::api::Mirror<>::peer_get_attributes(io_ctx, uuid, &attributes);
+  int r = librbd::api::Mirror<>::peer_site_get_attributes(
+    io_ctx, uuid, &attributes);
   if (r < 0) {
     return r;
   }
@@ -2931,7 +3203,7 @@ extern "C" int rbd_mirror_peer_get_attributes(
   return 0;
 }
 
-extern "C" int rbd_mirror_peer_set_attributes(
+extern "C" int rbd_mirror_peer_site_set_attributes(
     rados_ioctx_t p, const char *uuid, const char *keys, const char *values,
     size_t count) {
   librados::IoCtx io_ctx;
@@ -2947,7 +3219,126 @@ extern "C" int rbd_mirror_peer_set_attributes(
     attributes[key] = value;
   }
 
-  return librbd::api::Mirror<>::peer_set_attributes(io_ctx, uuid, attributes);
+  return librbd::api::Mirror<>::peer_site_set_attributes(
+    io_ctx, uuid, attributes);
+}
+
+extern "C" int rbd_mirror_image_global_status_list(rados_ioctx_t p,
+    const char *start_id, size_t max, char **image_ids,
+    rbd_mirror_image_global_status_t *images, size_t *len) {
+  librados::IoCtx io_ctx;
+  librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
+  std::map<std::string, librbd::mirror_image_global_status_t> cpp_images;
+
+  int r = librbd::api::Mirror<>::image_global_status_list(
+    io_ctx, start_id, max, &cpp_images);
+  if (r < 0) {
+    return r;
+  }
+
+  size_t i = 0;
+  for (auto &it : cpp_images) {
+    ceph_assert(i < max);
+    const std::string &image_id = it.first;
+    image_ids[i] = strdup(image_id.c_str());
+    mirror_image_global_status_cpp_to_c(it.second, &images[i]);
+    i++;
+  }
+  *len = i;
+  return 0;
+}
+
+extern "C" void rbd_mirror_image_global_status_cleanup(
+    rbd_mirror_image_global_status_t *global_status) {
+  free(global_status->name);
+  free(global_status->info.global_id);
+  for (auto idx = 0U; idx < global_status->site_statuses_count; ++idx) {
+    free(global_status->site_statuses[idx].fsid);
+    free(global_status->site_statuses[idx].description);
+  }
+  free(global_status->site_statuses);
+}
+
+extern "C" void rbd_mirror_image_global_status_list_cleanup(
+    char **image_ids, rbd_mirror_image_global_status_t *images, size_t len) {
+  for (size_t i = 0; i < len; i++) {
+    free(image_ids[i]);
+    rbd_mirror_image_global_status_cleanup(&images[i]);
+  }
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+extern "C" int rbd_mirror_peer_add(rados_ioctx_t p, char *uuid,
+                                   size_t uuid_max_length,
+                                   const char *cluster_name,
+                                   const char *client_name) {
+  return rbd_mirror_peer_site_add(
+    p, uuid, uuid_max_length, RBD_MIRROR_PEER_DIRECTION_RX_TX, cluster_name,
+    client_name);
+}
+
+extern "C" int rbd_mirror_peer_remove(rados_ioctx_t p, const char *uuid) {
+  return rbd_mirror_peer_site_remove(p, uuid);
+}
+
+extern "C" int rbd_mirror_peer_list(rados_ioctx_t p,
+                                    rbd_mirror_peer_t *peers, int *max_peers) {
+  librados::IoCtx io_ctx;
+  librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
+
+  std::vector<librbd::mirror_peer_site_t> peer_vector;
+  int r = librbd::api::Mirror<>::peer_site_list(io_ctx, &peer_vector);
+  if (r < 0) {
+    return r;
+  }
+
+  if (*max_peers < static_cast<int>(peer_vector.size())) {
+    *max_peers = static_cast<int>(peer_vector.size());
+    return -ERANGE;
+  }
+
+  for (int i = 0; i < static_cast<int>(peer_vector.size()); ++i) {
+    peers[i].uuid = strdup(peer_vector[i].uuid.c_str());
+    peers[i].cluster_name = strdup(peer_vector[i].site_name.c_str());
+    peers[i].client_name = strdup(peer_vector[i].client_name.c_str());
+  }
+  *max_peers = static_cast<int>(peer_vector.size());
+  return 0;
+}
+
+extern "C" void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers,
+                                             int max_peers) {
+  for (int i = 0; i < max_peers; ++i) {
+    free(peers[i].uuid);
+    free(peers[i].cluster_name);
+    free(peers[i].client_name);
+  }
+}
+
+extern "C" int rbd_mirror_peer_set_client(rados_ioctx_t p, const char *uuid,
+                                          const char *client_name) {
+  return rbd_mirror_peer_site_set_client_name(p, uuid, client_name);
+}
+
+extern "C" int rbd_mirror_peer_set_cluster(rados_ioctx_t p, const char *uuid,
+                                           const char *cluster_name) {
+  return rbd_mirror_peer_site_set_name(p, uuid, cluster_name);
+}
+
+extern "C" int rbd_mirror_peer_get_attributes(
+    rados_ioctx_t p, const char *uuid, char *keys, size_t *max_key_len,
+    char *values, size_t *max_val_len, size_t *key_value_count) {
+  return rbd_mirror_peer_site_get_attributes(
+    p, uuid, keys, max_key_len, values, max_val_len, key_value_count);
+}
+
+extern "C" int rbd_mirror_peer_set_attributes(
+    rados_ioctx_t p, const char *uuid, const char *keys, const char *values,
+    size_t count) {
+  return rbd_mirror_peer_site_set_attributes(
+    p, uuid, keys, values, count);
 }
 
 extern "C" int rbd_mirror_image_status_list(rados_ioctx_t p,
@@ -2955,10 +3346,10 @@ extern "C" int rbd_mirror_image_status_list(rados_ioctx_t p,
     rbd_mirror_image_status_t *images, size_t *len) {
   librados::IoCtx io_ctx;
   librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
-  std::map<std::string, librbd::mirror_image_status_t> cpp_images;
+  std::map<std::string, librbd::mirror_image_global_status_t> cpp_images;
 
-  int r = librbd::api::Mirror<>::image_status_list(io_ctx, start_id, max,
-                                                   &cpp_images);
+  int r = librbd::api::Mirror<>::image_global_status_list(
+    io_ctx, start_id, max, &cpp_images);
   if (r < 0) {
     return r;
   }
@@ -2968,7 +3359,7 @@ extern "C" int rbd_mirror_image_status_list(rados_ioctx_t p,
     ceph_assert(i < max);
     const std::string &image_id = it.first;
     image_ids[i] = strdup(image_id.c_str());
-    mirror_image_status_cpp_to_c(it.second, &images[i]);
+    mirror_image_global_status_cpp_to_c(it.second, &images[i]);
     i++;
   }
   *len = i;
@@ -2985,6 +3376,8 @@ extern "C" void rbd_mirror_image_status_list_cleanup(char **image_ids,
   }
 }
 
+#pragma GCC diagnostic pop
+
 extern "C" int rbd_mirror_image_status_summary(rados_ioctx_t p,
     rbd_mirror_image_status_state_t *states, int *counts, size_t *maxlen) {
 
@@ -5668,6 +6061,29 @@ extern "C" int rbd_mirror_image_get_info(rbd_image_t image,
   return 0;
 }
 
+extern "C" int rbd_mirror_image_get_global_status(
+    rbd_image_t image, rbd_mirror_image_global_status_t *status,
+    size_t status_size)
+{
+  librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+
+  if (sizeof(rbd_mirror_image_global_status_t) != status_size) {
+    return -ERANGE;
+  }
+
+  librbd::mirror_image_global_status_t cpp_status;
+  int r = librbd::api::Mirror<>::image_get_global_status(ictx, &cpp_status);
+  if (r < 0) {
+    return r;
+  }
+
+  mirror_image_global_status_cpp_to_c(cpp_status, status);
+  return 0;
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
 extern "C" int rbd_mirror_image_get_status(rbd_image_t image,
                                           rbd_mirror_image_status_t *status,
                                           size_t status_size)
@@ -5678,16 +6094,18 @@ extern "C" int rbd_mirror_image_get_status(rbd_image_t image,
     return -ERANGE;
   }
 
-  librbd::mirror_image_status_t cpp_status;
-  int r = librbd::api::Mirror<>::image_get_status(ictx, &cpp_status);
+  librbd::mirror_image_global_status_t cpp_status;
+  int r = librbd::api::Mirror<>::image_get_global_status(ictx, &cpp_status);
   if (r < 0) {
     return r;
   }
 
-  mirror_image_status_cpp_to_c(cpp_status, status);
+  mirror_image_global_status_cpp_to_c(cpp_status, status);
   return 0;
 }
 
+#pragma GCC diagnostic pop
+
 extern "C" int rbd_mirror_image_get_instance_id(rbd_image_t image,
                                                 char *instance_id,
                                                 size_t *instance_id_max_length)
@@ -5749,10 +6167,30 @@ extern "C" int rbd_aio_mirror_image_get_info(rbd_image_t image,
   return 0;
 }
 
-extern "C" int rbd_aio_mirror_image_get_status(rbd_image_t image,
-                                               rbd_mirror_image_status_t *status,
-                                               size_t status_size,
-                                               rbd_completion_t c) {
+extern "C" int rbd_aio_mirror_image_get_global_status(
+    rbd_image_t image, rbd_mirror_image_global_status_t *status,
+    size_t status_size, rbd_completion_t c) {
+  librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+  librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
+
+  if (sizeof(rbd_mirror_image_global_status_t) != status_size) {
+    return -ERANGE;
+  }
+
+  auto ctx = new C_MirrorImageGetGlobalStatus(
+    status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
+                                get_aio_completion(comp)));
+  librbd::api::Mirror<>::image_get_global_status(
+    ictx, &ctx->cpp_mirror_image_global_status, ctx);
+  return 0;
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+extern "C" int rbd_aio_mirror_image_get_status(
+    rbd_image_t image, rbd_mirror_image_status_t *status, size_t status_size,
+    rbd_completion_t c) {
   librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
   librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
 
@@ -5763,11 +6201,13 @@ extern "C" int rbd_aio_mirror_image_get_status(rbd_image_t image,
   auto ctx = new C_MirrorImageGetStatus(
     status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC,
                                 get_aio_completion(comp)));
-  librbd::api::Mirror<>::image_get_status(ictx, &ctx->cpp_mirror_image_status,
-                                          ctx);
+  librbd::api::Mirror<>::image_get_global_status(
+    ictx, &ctx->cpp_mirror_image_global_status, ctx);
   return 0;
 }
 
+#pragma GCC diagnostic pop
+
 extern "C" int rbd_update_watch(rbd_image_t image, uint64_t *handle,
                                rbd_update_callback_t watch_cb, void *arg)
 {
index 9aae566c623676c9a828f7fcdf0d9832933d064c..dd2c78d25a076dd7a8e1d43156aafec28bc5fe4a 100644 (file)
@@ -159,10 +159,13 @@ cdef extern from "rbd/librbd.h" nogil:
         _RBD_MIRROR_PEER_DIRECTION_TX "RBD_MIRROR_PEER_DIRECTION_TX"
         _RBD_MIRROR_PEER_DIRECTION_RX_TX "RBD_MIRROR_PEER_DIRECTION_RX_TX"
 
-    ctypedef struct rbd_mirror_peer_t:
+    ctypedef struct rbd_mirror_peer_site_t:
         char *uuid
-        char *cluster_name
+        rbd_mirror_peer_direction_t direction
+        char *site_name
+        char *fsid
         char *client_name
+        time_t last_seen
 
     cdef char* _RBD_MIRROR_PEER_ATTRIBUTE_NAME_MON_HOST "RBD_MIRROR_PEER_ATTRIBUTE_NAME_MON_HOST"
     cdef char* _RBD_MIRROR_PEER_ATTRIBUTE_NAME_KEY "RBD_MIRROR_PEER_ATTRIBUTE_NAME_KEY"
@@ -186,14 +189,19 @@ cdef extern from "rbd/librbd.h" nogil:
         _MIRROR_IMAGE_STATUS_STATE_STOPPING_REPLAY "MIRROR_IMAGE_STATUS_STATE_STOPPING_REPLAY"
         _MIRROR_IMAGE_STATUS_STATE_STOPPED "MIRROR_IMAGE_STATUS_STATE_STOPPED"
 
-    ctypedef struct rbd_mirror_image_status_t:
-        char *name
-        rbd_mirror_image_info_t info
+    ctypedef struct rbd_mirror_image_site_status_t:
+        char *fsid
         rbd_mirror_image_status_state_t state
         char *description
         time_t last_update
         bint up
 
+    ctypedef struct rbd_mirror_image_global_status_t:
+        char *name
+        rbd_mirror_image_info_t info
+        uint32_t site_statuses_count
+        rbd_mirror_image_site_status_t *site_statuses
+
     ctypedef enum rbd_lock_mode_t:
         _RBD_LOCK_MODE_EXCLUSIVE "RBD_LOCK_MODE_EXCLUSIVE"
         _RBD_LOCK_MODE_SHARED "RBD_LOCK_MODE_SHARED"
@@ -358,32 +366,33 @@ cdef extern from "rbd/librbd.h" nogil:
         rados_ioctx_t io_ctx, rbd_mirror_peer_direction_t direction,
         const char *token)
 
-    int rbd_mirror_peer_add(rados_ioctx_t io, char *uuid,
-                            size_t uuid_max_length, const char *cluster_name,
-                            const char *client_name)
-    int rbd_mirror_peer_remove(rados_ioctx_t io, const char *uuid)
-    int rbd_mirror_peer_list(rados_ioctx_t io_ctx, rbd_mirror_peer_t *peers,
-                             int *max_peers)
-    void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers, int max_peers)
-    int rbd_mirror_peer_set_client(rados_ioctx_t io, const char *uuid,
-                                   const char *client_name)
-    int rbd_mirror_peer_set_cluster(rados_ioctx_t io_ctx, const char *uuid,
-                                    const char *cluster_name)
-    int rbd_mirror_peer_get_attributes(rados_ioctx_t io_ctx, const char *uuid,
-                                       char *keys, size_t *max_key_len,
-                                       char *values, size_t *max_val_length,
-                                       size_t *key_value_count)
-    int rbd_mirror_peer_set_attributes(rados_ioctx_t io_ctx, const char *uuid,
-                                       const char *keys, const char *values,
-                                       size_t count)
-
-    int rbd_mirror_image_status_list(rados_ioctx_t io, const char *start_id,
-                                     size_t max, char **image_ids,
-                                     rbd_mirror_image_status_t *images,
-                                     size_t *len)
-    void rbd_mirror_image_status_list_cleanup(char **image_ids,
-                                              rbd_mirror_image_status_t *images,
-                                              size_t len)
+    int rbd_mirror_peer_site_add(
+        rados_ioctx_t io, char *uuid, size_t uuid_max_length,
+        rbd_mirror_peer_direction_t direction, const char *site_name,
+        const char *client_name)
+    int rbd_mirror_peer_site_remove(rados_ioctx_t io, const char *uuid)
+    int rbd_mirror_peer_site_list(
+        rados_ioctx_t io_ctx, rbd_mirror_peer_site_t *peers,int *max_peers)
+    void rbd_mirror_peer_site_list_cleanup(
+        rbd_mirror_peer_site_t *peers, int max_peers)
+
+    int rbd_mirror_peer_site_set_name(
+        rados_ioctx_t io_ctx, const char *uuid, const char *site_name)
+    int rbd_mirror_peer_site_set_client_name(
+        rados_ioctx_t io_ctx, const char *uuid, const char *client_name)
+
+    int rbd_mirror_peer_site_get_attributes(
+        rados_ioctx_t io_ctx, const char *uuid, char *keys, size_t *max_key_len,
+        char *values, size_t *max_val_length, size_t *key_value_count)
+    int rbd_mirror_peer_site_set_attributes(
+        rados_ioctx_t io_ctx, const char *uuid, const char *keys,
+        const char *values, size_t count)
+
+    int rbd_mirror_image_global_status_list(
+        rados_ioctx_t io, const char *start_id, size_t max, char **image_ids,
+        rbd_mirror_image_global_status_t *images, size_t *len)
+    void rbd_mirror_image_global_status_list_cleanup(
+        char **image_ids, rbd_mirror_image_global_status_t *images, size_t len)
     int rbd_mirror_image_status_summary(rados_ioctx_t io,
                                         rbd_mirror_image_status_state_t *states,
                                         int *counts, size_t *maxlen)
@@ -540,9 +549,12 @@ cdef extern from "rbd/librbd.h" nogil:
     int rbd_mirror_image_get_info(rbd_image_t image,
                                   rbd_mirror_image_info_t *mirror_image_info,
                                   size_t info_size)
-    int rbd_mirror_image_get_status(rbd_image_t image,
-                                    rbd_mirror_image_status_t *mirror_image_status,
-                                    size_t status_size)
+    int rbd_mirror_image_get_global_status(
+        rbd_image_t image,
+        rbd_mirror_image_global_status_t *mirror_image_global_status,
+        size_t status_size)
+    void rbd_mirror_image_global_status_cleanup(
+        rbd_mirror_image_global_status_t *mirror_image_global_status)
     int rbd_mirror_image_get_instance_id(rbd_image_t image, char *instance_id,
                                          size_t *id_max_length)
 
@@ -1834,30 +1846,34 @@ class RBD(object):
         if ret != 0:
             raise make_ex(ret, 'error importing bootstrap token')
 
-    def mirror_peer_add(self, ioctx, cluster_name, client_name):
+    def mirror_peer_add(self, ioctx, site_name, client_name,
+                        direction=RBD_MIRROR_PEER_DIRECTION_RX_TX):
         """
         Add mirror peer.
 
         :param ioctx: determines which RADOS pool is used
         :type ioctx: :class:`rados.Ioctx`
-        :param cluster_name: mirror peer cluster name
-        :type cluster_name: str
+        :param site_name: mirror peer site name
+        :type site_name: str
         :param client_name: mirror peer client name
         :type client_name: str
+        :param direction: the direction of the mirroring
+        :type direction: int
         :returns: str - peer uuid
         """
-        cluster_name = cstr(cluster_name, 'cluster_name')
+        site_name = cstr(site_name, 'site_name')
         client_name = cstr(client_name, 'client_name')
         cdef:
             rados_ioctx_t _ioctx = convert_ioctx(ioctx)
             char *_uuid = NULL
             size_t _uuid_max_length = 512
-            char *_cluster_name = cluster_name
+            rbd_mirror_peer_direction_t _direction = direction
+            char *_site_name = site_name
             char *_client_name = client_name
         try:
             _uuid = <char *>realloc_chk(_uuid, _uuid_max_length)
-            ret = rbd_mirror_peer_add(_ioctx, _uuid, _uuid_max_length,
-                                      _cluster_name, _client_name)
+            ret = rbd_mirror_peer_site_add(_ioctx, _uuid, _uuid_max_length,
+                                           _direction, _site_name, _client_name)
             if ret != 0:
                 raise make_ex(ret, 'error adding mirror peer')
             return decode_cstr(_uuid)
@@ -1878,7 +1894,7 @@ class RBD(object):
             rados_ioctx_t _ioctx = convert_ioctx(ioctx)
             char *_uuid = uuid
         with nogil:
-            ret = rbd_mirror_peer_remove(_ioctx, _uuid)
+            ret = rbd_mirror_peer_site_remove(_ioctx, _uuid)
         if ret != 0:
             raise make_ex(ret, 'error removing mirror peer')
 
@@ -1910,31 +1926,35 @@ class RBD(object):
             char *_uuid = uuid
             char *_client_name = client_name
         with nogil:
-            ret = rbd_mirror_peer_set_client(_ioctx, _uuid, _client_name)
+            ret = rbd_mirror_peer_site_set_client_name(_ioctx, _uuid,
+                                                       _client_name)
         if ret != 0:
-            raise make_ex(ret, 'error setting mirror peer client')
+            raise make_ex(ret, 'error setting mirror peer client name')
 
-    def mirror_peer_set_cluster(self, ioctx, uuid, cluster_name):
+    def mirror_peer_set_name(self, ioctx, uuid, site_name):
         """
-        Set mirror peer cluster name
+        Set mirror peer site name
 
         :param ioctx: determines which RADOS pool is written
         :type ioctx: :class:`rados.Ioctx`
         :param uuid: uuid of the mirror peer
         :type uuid: str
-        :param cluster_name: cluster name of the mirror peer to set
-        :type cluster_name: str
+        :param site_name: site name of the mirror peer to set
+        :type site_name: str
         """
         uuid = cstr(uuid, 'uuid')
-        cluster_name = cstr(cluster_name, 'cluster_name')
+        site_name = cstr(site_name, 'site_name')
         cdef:
             rados_ioctx_t _ioctx = convert_ioctx(ioctx)
             char *_uuid = uuid
-            char *_cluster_name = cluster_name
+            char *_site_name = site_name
         with nogil:
-            ret = rbd_mirror_peer_set_cluster(_ioctx, _uuid, _cluster_name)
+            ret = rbd_mirror_peer_site_set_name(_ioctx, _uuid, _site_name)
         if ret != 0:
-            raise make_ex(ret, 'error setting mirror peer cluster')
+            raise make_ex(ret, 'error setting mirror peer site name')
+
+    def mirror_peer_set_cluster(self, ioctx, uuid, cluster_name):
+        self.mirror_peer_set_name(ioctx, uuid, cluster_name)
 
     def mirror_peer_get_attributes(self, ioctx, uuid):
         """
@@ -1965,9 +1985,9 @@ class RBD(object):
                 _keys = <char *>realloc_chk(_keys, _keys_size)
                 _vals = <char *>realloc_chk(_vals, _vals_size)
                 with nogil:
-                    ret = rbd_mirror_peer_get_attributes(_ioctx, _uuid, _keys,
-                                                         &_keys_size, _vals,
-                                                         &_vals_size, &_count)
+                    ret = rbd_mirror_peer_site_get_attributes(
+                        _ioctx, _uuid, _keys, &_keys_size, _vals, &_vals_size,
+                        &_count)
                 if ret >= 0:
                     break
                 elif ret != -errno.ERANGE:
@@ -2001,8 +2021,8 @@ class RBD(object):
             size_t _count = len(attributes)
 
         with nogil:
-            ret = rbd_mirror_peer_set_attributes(_ioctx, _uuid, _keys, _vals,
-                                                 _count)
+            ret = rbd_mirror_peer_site_set_attributes(_ioctx, _uuid, _keys,
+                                                      _vals, _count)
         if ret != 0:
             raise make_ex(ret, 'error setting mirror peer attributes')
 
@@ -2424,13 +2444,17 @@ cdef class MirrorPeerIterator(object):
 
     * ``uuid`` (str) - uuid of the peer
 
-    * ``cluster_name`` (str) - cluster name of the peer
+    * ``direction`` (int) - direction enum
+
+    * ``site_name`` (str) - cluster name of the peer
+
+    * ``fsid`` (str) - fsid of the peer
 
     * ``client_name`` (str) - client name of the peer
     """
 
     cdef:
-        rbd_mirror_peer_t *peers
+        rbd_mirror_peer_site_t *peers
         int num_peers
 
     def __init__(self, ioctx):
@@ -2439,10 +2463,11 @@ cdef class MirrorPeerIterator(object):
         self.peers = NULL
         self.num_peers = 10
         while True:
-            self.peers = <rbd_mirror_peer_t *>realloc_chk(
-                self.peers, self.num_peers * sizeof(rbd_mirror_peer_t))
+            self.peers = <rbd_mirror_peer_site_t *>realloc_chk(
+                self.peers, self.num_peers * sizeof(rbd_mirror_peer_site_t))
             with nogil:
-                ret = rbd_mirror_peer_list(_ioctx, self.peers, &self.num_peers)
+                ret = rbd_mirror_peer_site_list(_ioctx, self.peers,
+                                                &self.num_peers)
             if ret < 0:
                 if ret == -errno.ERANGE:
                     continue
@@ -2454,13 +2479,16 @@ cdef class MirrorPeerIterator(object):
         for i in range(self.num_peers):
             yield {
                 'uuid'         : decode_cstr(self.peers[i].uuid),
-                'cluster_name' : decode_cstr(self.peers[i].cluster_name),
+                'direction'    : int(self.peers[i].direction),
+                'site_name'    : decode_cstr(self.peers[i].site_name),
+                'cluster_name' : decode_cstr(self.peers[i].site_name),
+                'fsid'         : decode_cstr(self.peers[i].fsid),
                 'client_name'  : decode_cstr(self.peers[i].client_name),
                 }
 
     def __dealloc__(self):
         if self.peers:
-            rbd_mirror_peer_list_cleanup(self.peers, self.num_peers)
+            rbd_mirror_peer_site_list_cleanup(self.peers, self.num_peers)
             free(self.peers)
 
 cdef class MirrorImageStatusIterator(object):
@@ -2475,15 +2503,27 @@ cdef class MirrorImageStatusIterator(object):
 
         * ``id`` (str) - mirror image id
 
-        * `info` (dict) - mirror image info
+        * ``info`` (dict) - mirror image info
 
-        * `state` (int) - mirror state
+        * ``state`` (int) - status mirror state
 
-        * `description` (str) - status description
+        * ``description`` (str) - status description
 
-        * `last_update` (datetime) - last status update time
+        * ``last_update`` (datetime) - last status update time
 
         * ``up`` (bool) - is mirroring agent up
+
+        * ``remote_statuses`` (array) -
+
+        *   ``fsid`` (str) - remote fsid
+
+        *   ``state`` (int) - status mirror state
+
+        *   ``description`` (str) - status description
+
+        *   ``last_update`` (datetime) - last status update time
+
+        *   ``up`` (bool) - is mirroring agent up
     """
 
     cdef:
@@ -2491,7 +2531,8 @@ cdef class MirrorImageStatusIterator(object):
         size_t max_read
         char *last_read
         char **image_ids
-        rbd_mirror_image_status_t *images
+        rbd_mirror_image_site_status_t *s_status
+        rbd_mirror_image_global_status_t *images
         size_t size
 
     def __init__(self, ioctx):
@@ -2500,33 +2541,52 @@ cdef class MirrorImageStatusIterator(object):
         self.last_read = strdup("")
         self.image_ids = <char **>realloc_chk(NULL,
             sizeof(char *) * self.max_read)
-        self.images = <rbd_mirror_image_status_t *>realloc_chk(NULL,
-            sizeof(rbd_mirror_image_status_t) * self.max_read)
+        self.images = <rbd_mirror_image_global_status_t *>realloc_chk(NULL,
+            sizeof(rbd_mirror_image_global_status_t) * self.max_read)
         self.size = 0
         self.get_next_chunk()
 
+
     def __iter__(self):
         while self.size > 0:
             for i in range(self.size):
-                yield {
+                local_status = None
+                site_statuses = []
+
+                for x in range(self.images[i].site_statuses_count):
+                    s_status = &self.images[i].site_statuses[x]
+                    site_status = {
+                        'state'       : s_status.state,
+                        'description' : decode_cstr(s_status.description),
+                        'last_update' : datetime.utcfromtimestamp(s_status.last_update),
+                        'up'          : s_status.up,
+                        }
+                    fsid = decode_cstr(s_status.fsid)
+                    if fsid == '':
+                        local_status = site_status
+                    else:
+                        site_status['fsid'] = fsid
+                        site_statuses += site_status
+
+                status = {
                     'name'        : decode_cstr(self.images[i].name),
                     'id'          : decode_cstr(self.image_ids[i]),
                     'info'        : {
                         'global_id' : decode_cstr(self.images[i].info.global_id),
                         'state'     : self.images[i].info.state,
                         },
-                    'state'       : self.images[i].state,
-                    'description' : decode_cstr(self.images[i].description),
-                    'last_update' : datetime.utcfromtimestamp(self.images[i].last_update),
-                    'up'          : self.images[i].up,
+                    'remote_statuses': site_statuses,
                     }
+                if local_status:
+                    status.update(local_status)
+                yield status
             if self.size < self.max_read:
                 break
             self.get_next_chunk()
 
     def __dealloc__(self):
-        rbd_mirror_image_status_list_cleanup(self.image_ids, self.images,
-                                             self.size)
+        rbd_mirror_image_global_status_list_cleanup(self.image_ids, self.images,
+                                                    self.size)
         if self.last_read:
             free(self.last_read)
         if self.image_ids:
@@ -2536,13 +2596,16 @@ cdef class MirrorImageStatusIterator(object):
 
     def get_next_chunk(self):
         if self.size > 0:
-            rbd_mirror_image_status_list_cleanup(self.image_ids, self.images,
-                                                 self.size)
+            rbd_mirror_image_global_status_list_cleanup(self.image_ids,
+                                                        self.images,
+                                                        self.size)
             self.size = 0
         with nogil:
-            ret = rbd_mirror_image_status_list(self.ioctx, self.last_read,
-                                               self.max_read, self.image_ids,
-                                               self.images, &self.size)
+            ret = rbd_mirror_image_global_status_list(self.ioctx,
+                                                      self.last_read,
+                                                      self.max_read,
+                                                      self.image_ids,
+                                                      self.images, &self.size)
         if ret < 0:
             raise make_ex(ret, 'error listing mirror images status')
         if self.size > 0:
@@ -4288,7 +4351,7 @@ written." % (self.name, ret, length))
 
             * ``id`` (str) - mirror image id
 
-            * `info` (dict) - mirror image info
+            * ``info`` (dict) - mirror image info
 
             * ``state`` (int) - status mirror state
 
@@ -4297,29 +4360,59 @@ written." % (self.name, ret, length))
             * ``last_update`` (datetime) - last status update time
 
             * ``up`` (bool) - is mirroring agent up
+
+            * ``remote_statuses`` (array) -
+
+            *   ``fsid`` (str) - remote fsid
+
+            *   ``state`` (int) - status mirror state
+
+            *   ``description`` (str) - status description
+
+            *   ``last_update`` (datetime) - last status update time
+
+            *   ``up`` (bool) - is mirroring agent up
         """
-        cdef rbd_mirror_image_status_t c_status
-        with nogil:
-            ret = rbd_mirror_image_get_status(self.image, &c_status,
-                                              sizeof(c_status))
-        if ret != 0:
-            raise make_ex(ret, 'error getting mirror status for image %s' % self.name)
-        status = {
-            'name'      : decode_cstr(c_status.name),
-            'id'        : self.id(),
-            'info'      : {
-                'global_id' : decode_cstr(c_status.info.global_id),
-                'state'     : int(c_status.info.state),
-                'primary'   : c_status.info.primary,
-                },
-            'state'       : c_status.state,
-            'description' : decode_cstr(c_status.description),
-            'last_update' : datetime.utcfromtimestamp(c_status.last_update),
-            'up'          : c_status.up,
-            }
-        free(c_status.name)
-        free(c_status.info.global_id)
-        free(c_status.description)
+        cdef:
+            rbd_mirror_image_site_status_t *s_status
+            rbd_mirror_image_global_status_t c_status
+        try:
+            with nogil:
+                ret = rbd_mirror_image_get_global_status(self.image, &c_status,
+                                                         sizeof(c_status))
+            if ret != 0:
+                raise make_ex(ret, 'error getting mirror status for image %s' % self.name)
+
+            local_status = None
+            site_statuses = []
+            for i in range(c_status.site_statuses_count):
+                s_status = &c_status.site_statuses[i]
+                site_status = {
+                    'state'       : s_status.state,
+                    'description' : decode_cstr(s_status.description),
+                    'last_update' : datetime.utcfromtimestamp(s_status.last_update),
+                    'up'          : s_status.up,
+                    }
+                fsid = decode_cstr(s_status.fsid)
+                if fsid == '':
+                    local_status = site_status
+                else:
+                    site_statuses['fsid'] = fsid
+                    site_statuses += site_status
+            status = {
+                'name': decode_cstr(c_status.name),
+                'id'  : self.id(),
+                'info': {
+                    'global_id' : decode_cstr(c_status.info.global_id),
+                    'state'     : int(c_status.info.state),
+                    'primary'   : c_status.info.primary,
+                    },
+                'remote_statuses': site_statuses,
+                }
+            if local_status:
+                status.update(local_status)
+        finally:
+            rbd_mirror_image_global_status_cleanup(&c_status)
         return status
 
     def mirror_image_get_instance_id(self):
index 204a38ff724d3b7a563da2d26441a58844400cbc..e7948c6284601dffdbd66d4b26777ca0966bfc2b 100644 (file)
 void register_test_mirroring() {
 }
 
+namespace librbd {
+
+static bool operator==(const mirror_peer_site_t& lhs,
+                       const mirror_peer_site_t& rhs) {
+  return (lhs.uuid == rhs.uuid &&
+          lhs.direction == rhs.direction &&
+          lhs.site_name == rhs.site_name &&
+          lhs.client_name == rhs.client_name &&
+          lhs.last_seen == rhs.last_seen);
+}
+
+static std::ostream& operator<<(std::ostream& os,
+                                const mirror_peer_site_t& rhs) {
+  os << "uuid=" << rhs.uuid << ", "
+     << "direction=" << rhs.direction << ", "
+     << "site_name=" << rhs.site_name << ", "
+     << "client_name=" << rhs.client_name << ", "
+     << "last_seen=" << rhs.last_seen;
+  return os;
+}
+
+};
+
 class TestMirroring : public TestFixture {
 public:
 
@@ -53,6 +76,22 @@ public:
 
   std::string image_name = "mirrorimg1";
 
+  int get_local_mirror_image_site_status(
+      const librbd::mirror_image_global_status_t& status,
+      librbd::mirror_image_site_status_t* local_status) {
+    auto it = std::find_if(status.site_statuses.begin(),
+                           status.site_statuses.end(),
+                           [](auto& site_status) {
+        return (site_status.fsid == RBD_MIRROR_IMAGE_STATUS_LOCAL_FSID);
+      });
+    if (it == status.site_statuses.end()) {
+      return -ENOENT;
+    }
+
+    *local_status = *it;
+    return 0;
+  }
+
   void check_mirror_image_enable(rbd_mirror_mode_t mirror_mode,
                                  uint64_t features,
                                  int expected_r,
@@ -73,9 +112,11 @@ public:
     ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image)));
     ASSERT_EQ(mirror_state, mirror_image.state);
 
-    librbd::mirror_image_status_t status;
-    ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status)));
-    ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state);
+    librbd::mirror_image_global_status_t status;
+    ASSERT_EQ(0, image.mirror_image_get_global_status(&status, sizeof(status)));
+    librbd::mirror_image_site_status_t local_status;
+    ASSERT_EQ(0, get_local_mirror_image_site_status(status, &local_status));
+    ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, local_status.state);
 
     std::string instance_id;
     ASSERT_EQ(mirror_state == RBD_MIRROR_IMAGE_ENABLED ? -ENOENT : -EINVAL,
@@ -106,9 +147,11 @@ public:
     ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image)));
     ASSERT_EQ(mirror_state, mirror_image.state);
 
-    librbd::mirror_image_status_t status;
-    ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status)));
-    ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state);
+    librbd::mirror_image_global_status_t status;
+    ASSERT_EQ(0, image.mirror_image_get_global_status(&status, sizeof(status)));
+    librbd::mirror_image_site_status_t local_status;
+    ASSERT_EQ(0, get_local_mirror_image_site_status(status, &local_status));
+    ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, local_status.state);
 
     std::string instance_id;
     ASSERT_EQ(mirror_state == RBD_MIRROR_IMAGE_ENABLED ? -ENOENT : -EINVAL,
@@ -128,8 +171,9 @@ public:
   }
 
   void check_mirroring_status(size_t *images_count) {
-    std::map<std::string, librbd::mirror_image_status_t> images;
-    ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, "", 4096, &images));
+    std::map<std::string, librbd::mirror_image_global_status_t> images;
+    ASSERT_EQ(0, m_rbd.mirror_image_global_status_list(m_ioctx, "", 4096,
+                                                       &images));
 
     std::map<librbd::mirror_image_status_state_t, int> states;
     ASSERT_EQ(0, m_rbd.mirror_image_status_summary(m_ioctx, &states));
@@ -165,9 +209,11 @@ public:
     ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image)));
     ASSERT_EQ(mirror_state, mirror_image.state);
 
-    librbd::mirror_image_status_t status;
-    ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status)));
-    ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state);
+    librbd::mirror_image_global_status_t status;
+    ASSERT_EQ(0, image.mirror_image_get_global_status(&status, sizeof(status)));
+    librbd::mirror_image_site_status_t local_status;
+    ASSERT_EQ(0, get_local_mirror_image_site_status(status, &local_status));
+    ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, local_status.state);
 
     size_t mirror_images_new_count = 0;
     check_mirroring_status(&mirror_images_new_count);
@@ -209,9 +255,11 @@ public:
     ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image)));
     ASSERT_EQ(mirror_state, mirror_image.state);
 
-    librbd::mirror_image_status_t status;
-    ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status)));
-    ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state);
+    librbd::mirror_image_global_status_t status;
+    ASSERT_EQ(0, image.mirror_image_get_global_status(&status, sizeof(status)));
+    librbd::mirror_image_site_status_t local_status;
+    ASSERT_EQ(0, get_local_mirror_image_site_status(status, &local_status));
+    ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, local_status.state);
 
     ASSERT_EQ(0, image.close());
     ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str()));
@@ -252,9 +300,12 @@ public:
       ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image)));
       ASSERT_EQ(mirror_state, mirror_image.state);
 
-      librbd::mirror_image_status_t status;
-      ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status)));
-      ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state);
+      librbd::mirror_image_global_status_t status;
+      ASSERT_EQ(0, image.mirror_image_get_global_status(&status,
+                                                        sizeof(status)));
+      librbd::mirror_image_site_status_t local_status;
+      ASSERT_EQ(0, get_local_mirror_image_site_status(status, &local_status));
+      ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, local_status.state);
 
       ASSERT_EQ(0, image.close());
       ASSERT_EQ(0, m_rbd.remove(m_ioctx, img_name_str.c_str()));
@@ -443,9 +494,11 @@ TEST_F(TestMirroring, DisableImageMirrorWithPeer) {
                                            sizeof(mirror_image)));
   ASSERT_EQ(RBD_MIRROR_IMAGE_DISABLED, mirror_image.state);
 
-  librbd::mirror_image_status_t status;
-  ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status)));
-  ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state);
+  librbd::mirror_image_global_status_t status;
+  ASSERT_EQ(0, image.mirror_image_get_global_status(&status, sizeof(status)));
+  librbd::mirror_image_site_status_t local_status;
+  ASSERT_EQ(0, get_local_mirror_image_site_status(status, &local_status));
+  ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, local_status.state);
 
   ASSERT_EQ(0, image.close());
   ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str()));
@@ -478,9 +531,11 @@ TEST_F(TestMirroring, DisableJournalingWithPeer) {
                                            sizeof(mirror_image)));
   ASSERT_EQ(RBD_MIRROR_IMAGE_DISABLED, mirror_image.state);
 
-  librbd::mirror_image_status_t status;
-  ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status)));
-  ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state);
+  librbd::mirror_image_global_status_t status;
+  ASSERT_EQ(0, image.mirror_image_get_global_status(&status, sizeof(status)));
+  librbd::mirror_image_site_status_t local_status;
+  ASSERT_EQ(0, get_local_mirror_image_site_status(status, &local_status));
+  ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, local_status.state);
 
   ASSERT_EQ(0, image.close());
   ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str()));
@@ -732,23 +787,27 @@ TEST_F(TestMirroring, MirrorStatusList) {
   setup_images_with_mirror_mode(RBD_MIRROR_MODE_POOL, features_vec);
 
   std::string last_read = "";
-  std::map<std::string, librbd::mirror_image_status_t> images;
-  ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, last_read, 2, &images));
+  std::map<std::string, librbd::mirror_image_global_status_t> images;
+  ASSERT_EQ(0, m_rbd.mirror_image_global_status_list(m_ioctx, last_read, 2,
+                                                     &images));
   ASSERT_EQ(2U, images.size());
 
   last_read = images.rbegin()->first;
   images.clear();
-  ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, last_read, 2, &images));
+  ASSERT_EQ(0, m_rbd.mirror_image_global_status_list(m_ioctx, last_read, 2,
+                                                     &images));
   ASSERT_EQ(2U, images.size());
 
   last_read = images.rbegin()->first;
   images.clear();
-  ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, last_read, 4096, &images));
+  ASSERT_EQ(0, m_rbd.mirror_image_global_status_list(m_ioctx, last_read, 4096,
+                                                     &images));
   ASSERT_EQ(1U, images.size());
 
   last_read = images.rbegin()->first;
   images.clear();
-  ASSERT_EQ(0, m_rbd.mirror_image_status_list(m_ioctx, last_read, 4096, &images));
+  ASSERT_EQ(0, m_rbd.mirror_image_global_status_list(m_ioctx, last_read, 4096,
+                                                     &images));
   ASSERT_EQ(0U, images.size());
 }
 
@@ -923,13 +982,13 @@ TEST_F(TestMirroring, AioGetStatus) {
   }
 
   std::list<librbd::RBD::AioCompletion *> aio_comps;
-  std::list<librbd::mirror_image_status_t> statuses;
+  std::list<librbd::mirror_image_global_status_t> statuses;
   for (auto &image : images) {
     aio_comps.push_back(new librbd::RBD::AioCompletion(nullptr, nullptr));
     statuses.emplace_back();
-    ASSERT_EQ(0, image.aio_mirror_image_get_status(&statuses.back(),
-                                                   sizeof(statuses.back()),
-                                                   aio_comps.back()));
+    ASSERT_EQ(0, image.aio_mirror_image_get_global_status(
+                   &statuses.back(), sizeof(statuses.back()),
+                   aio_comps.back()));
   }
   for (auto aio_comp : aio_comps) {
     ASSERT_EQ(0, aio_comp->wait_for_complete());
@@ -944,10 +1003,13 @@ TEST_F(TestMirroring, AioGetStatus) {
     ASSERT_NE("", status.info.global_id);
     ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, status.info.state);
     ASSERT_TRUE(status.info.primary);
-    ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state);
-    ASSERT_EQ("status not found", status.description);
-    ASSERT_FALSE(status.up);
-    ASSERT_EQ(0, status.last_update);
+
+    librbd::mirror_image_site_status_t local_status;
+    ASSERT_EQ(0, get_local_mirror_image_site_status(status, &local_status));
+    ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, local_status.state);
+    ASSERT_EQ("status not found", local_status.description);
+    ASSERT_FALSE(local_status.up);
+    ASSERT_EQ(0, local_status.last_update);
   }
 }
 
@@ -990,3 +1052,30 @@ TEST_F(TestMirroring, Bootstrap) {
             m_rbd.mirror_peer_bootstrap_import(
               m_ioctx, RBD_MIRROR_PEER_DIRECTION_RX, token_b64));
 }
+
+TEST_F(TestMirroring, PeerDirection) {
+  ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_POOL));
+
+  std::string uuid;
+  ASSERT_EQ(-EINVAL, m_rbd.mirror_peer_site_add(
+                       m_ioctx, &uuid, RBD_MIRROR_PEER_DIRECTION_TX, "siteA",
+                       "client.admin"));
+  ASSERT_EQ(0, m_rbd.mirror_peer_site_add(m_ioctx, &uuid,
+                                          RBD_MIRROR_PEER_DIRECTION_RX_TX,
+                                          "siteA", "client.admin"));
+
+  std::vector<librbd::mirror_peer_site_t> peers;
+  ASSERT_EQ(0, m_rbd.mirror_peer_site_list(m_ioctx, &peers));
+  std::vector<librbd::mirror_peer_site_t> expected_peers = {
+    {uuid, RBD_MIRROR_PEER_DIRECTION_RX_TX, "siteA", "", "client.admin", 0}};
+  ASSERT_EQ(expected_peers, peers);
+
+  ASSERT_EQ(0, m_rbd.mirror_peer_site_set_direction(
+                 m_ioctx, uuid, RBD_MIRROR_PEER_DIRECTION_RX));
+  ASSERT_EQ(0, m_rbd.mirror_peer_site_list(m_ioctx, &peers));
+  expected_peers = {
+    {uuid, RBD_MIRROR_PEER_DIRECTION_RX, "siteA", "", "client.admin", 0}};
+  ASSERT_EQ(expected_peers, peers);
+
+  ASSERT_EQ(0, m_rbd.mirror_peer_site_remove(m_ioctx, uuid));
+}
index 1f2a5b8ddd862d0a54aabc1e6a85937b6c90d65e..cead2a8302f6bbfb3deea9cb3eb1f591dc22556c 100644 (file)
@@ -1,5 +1,6 @@
 # vim: expandtab smarttab shiftwidth=4 softtabstop=4
 import base64
+import copy
 import errno
 import functools
 import json
@@ -31,7 +32,7 @@ from rbd import (RBD, Group, Image, ImageNotFound, InvalidArgument, ImageExists,
                  RBD_CONFIG_SOURCE_POOL, RBD_CONFIG_SOURCE_IMAGE,
                  RBD_MIRROR_PEER_ATTRIBUTE_NAME_MON_HOST,
                  RBD_MIRROR_PEER_ATTRIBUTE_NAME_KEY,
-                 RBD_MIRROR_PEER_DIRECTION_RX)
+                 RBD_MIRROR_PEER_DIRECTION_RX, RBD_MIRROR_PEER_DIRECTION_RX_TX)
 
 rados = None
 ioctx = None
@@ -1819,13 +1820,17 @@ class TestMirroring(object):
 
     def test_mirror_peer(self):
         eq([], list(self.rbd.mirror_peer_list(ioctx)))
-        cluster_name = "test_cluster"
+        site_name = "test_site"
         client_name = "test_client"
-        uuid = self.rbd.mirror_peer_add(ioctx, cluster_name, client_name)
+        uuid = self.rbd.mirror_peer_add(ioctx, site_name, client_name,
+                                        direction=RBD_MIRROR_PEER_DIRECTION_RX_TX)
         assert(uuid)
         peer = {
             'uuid' : uuid,
-            'cluster_name' : cluster_name,
+            'direction': RBD_MIRROR_PEER_DIRECTION_RX_TX,
+            'site_name' : site_name,
+            'cluster_name' : site_name,
+            'fsid': '',
             'client_name' : client_name,
             }
         eq([peer], list(self.rbd.mirror_peer_list(ioctx)))
@@ -1835,7 +1840,10 @@ class TestMirroring(object):
         self.rbd.mirror_peer_set_client(ioctx, uuid, client_name)
         peer = {
             'uuid' : uuid,
+            'direction': RBD_MIRROR_PEER_DIRECTION_RX_TX,
+            'site_name' : cluster_name,
             'cluster_name' : cluster_name,
+            'fsid': '',
             'client_name' : client_name,
             }
         eq([peer], list(self.rbd.mirror_peer_list(ioctx)))
@@ -1908,6 +1916,7 @@ class TestMirroring(object):
         eq(image_name, status['name'])
         eq(False, status['up'])
         eq(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status['state'])
+        eq([], status['remote_statuses'])
         info = status['info']
         self.check_info(info, global_id, state, primary)
 
index 436ab008e228f2b23b11d7b8d58892fba801040b..03fd3b14247e76bf27ff9570e1bca5741c1a4d26 100644 (file)
@@ -77,11 +77,10 @@ public:
                                                    RBD_MIRROR_MODE_POOL));
 
       std::string gen_uuid;
-      ASSERT_EQ(0, librbd::api::Mirror<>::peer_add(ioctx,
-                                                   uuid != nullptr ? uuid :
-                                                                     &gen_uuid,
-                                                  peer.cluster_name,
-                                                  peer.client_name));
+      ASSERT_EQ(0, librbd::api::Mirror<>::peer_site_add(
+                     ioctx, uuid != nullptr ? uuid : &gen_uuid,
+                     RBD_MIRROR_PEER_DIRECTION_RX_TX,
+                     peer.cluster_name, peer.client_name));
       m_pool_peers[pool_id].insert(peer);
     }
     if (name != nullptr) {
index 482e80e0d19c3295ca58a8ba649945c3f3e5e0a8..8433ab88afd2966973d495721dd1a95159b9f874 100644 (file)
@@ -107,9 +107,9 @@ public:
       ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(ioctx,
                                                    RBD_MIRROR_MODE_POOL));
       std::string uuid;
-      ASSERT_EQ(0, librbd::api::Mirror<>::peer_add(ioctx, &uuid,
-                                                   peer.cluster_name,
-                                                   peer.client_name));
+      ASSERT_EQ(0, librbd::api::Mirror<>::peer_site_add(
+        ioctx, &uuid, RBD_MIRROR_PEER_DIRECTION_RX_TX, peer.cluster_name,
+        peer.client_name));
     }
     if (name != nullptr) {
       *name = pool_name;
index 0e38a033ff55966c081b88bc28d5bbeb2661bdc2..75cc1f5102abb53182b6961147dec014a9b5db45 100644 (file)
@@ -32,8 +32,8 @@ set(rbd_srcs
   action/Lock.cc
   action/MergeDiff.cc
   action/Migration.cc
-  action/MirrorPool.cc
   action/MirrorImage.cc
+  action/MirrorPool.cc
   action/Namespace.cc
   action/Nbd.cc
   action/ObjectMap.cc
index d4f500226ed27ea17f91ed62443cae8e577f446a..e8cd5f293c3c4791dea3edc57860ee79e4920501 100644 (file)
@@ -850,7 +850,8 @@ std::string mirror_image_state(librbd::mirror_image_state_t state) {
   }
 }
 
-std::string mirror_image_status_state(librbd::mirror_image_status_state_t state) {
+std::string mirror_image_status_state(
+    librbd::mirror_image_status_state_t state) {
   switch (state) {
   case MIRROR_IMAGE_STATUS_STATE_UNKNOWN:
     return "unknown";
@@ -871,11 +872,39 @@ std::string mirror_image_status_state(librbd::mirror_image_status_state_t state)
   }
 }
 
-std::string mirror_image_status_state(librbd::mirror_image_status_t status) {
+std::string mirror_image_site_status_state(
+    const librbd::mirror_image_site_status_t& status) {
   return (status.up ? "up+" : "down+") +
     mirror_image_status_state(status.state);
 }
 
+std::string mirror_image_global_status_state(
+    const librbd::mirror_image_global_status_t& status) {
+  librbd::mirror_image_site_status_t local_status;
+  int r = get_local_mirror_image_status(status, &local_status);
+  if (r < 0) {
+    return "down+unknown";
+  }
+
+  return mirror_image_site_status_state(local_status);
+}
+
+int get_local_mirror_image_status(
+    const librbd::mirror_image_global_status_t& status,
+    librbd::mirror_image_site_status_t* local_status) {
+  auto it = std::find_if(status.site_statuses.begin(),
+                         status.site_statuses.end(),
+                         [](auto& site_status) {
+      return (site_status.fsid == RBD_MIRROR_IMAGE_STATUS_LOCAL_FSID);
+    });
+  if (it == status.site_statuses.end()) {
+    return -ENOENT;
+  }
+
+  *local_status = *it;
+  return 0;
+}
+
 std::string timestr(time_t t) {
   struct tm tm;
 
index 81ea2c714302cb6fbba224949f7334cb6fee33c0..c0bf0be0b70f99ab6ee2627210e01f07714859b6 100644 (file)
@@ -189,9 +189,18 @@ bool is_not_user_snap_namespace(librbd::Image* image,
 
 std::string image_id(librbd::Image& image);
 
-std::string mirror_image_state(librbd::mirror_image_state_t mirror_image_state);
-std::string mirror_image_status_state(librbd::mirror_image_status_state_t state);
-std::string mirror_image_status_state(librbd::mirror_image_status_t status);
+std::string mirror_image_state(
+    librbd::mirror_image_state_t mirror_image_state);
+std::string mirror_image_status_state(
+    librbd::mirror_image_status_state_t state);
+std::string mirror_image_site_status_state(
+    const librbd::mirror_image_site_status_t& status);
+std::string mirror_image_global_status_state(
+    const librbd::mirror_image_global_status_t& status);
+
+int get_local_mirror_image_status(
+    const librbd::mirror_image_global_status_t& status,
+    librbd::mirror_image_site_status_t* local_status);
 
 std::string timestr(time_t t);
 
index 14895c86eec0a76e97b235e93d5c3243925ff211..c9c4cf73b143db7df2d768eb5f89bbec8f950ee7 100644 (file)
@@ -275,8 +275,8 @@ int execute_status(const po::variables_map &vm,
     return r;
   }
 
-  librbd::mirror_image_status_t status;
-  r = image.mirror_image_get_status(&status, sizeof(status));
+  librbd::mirror_image_global_status_t status;
+  r = image.mirror_image_get_global_status(&status, sizeof(status));
   if (r < 0) {
     std::cerr << "rbd: failed to get status for image " << image_name << ": "
              << cpp_strerror(r) << std::endl;
@@ -286,7 +286,10 @@ int execute_status(const po::variables_map &vm,
   std::string instance_id;
   MirrorDaemonServiceInfo daemon_service_info(io_ctx);
 
-  if (status.up) {
+  librbd::mirror_image_site_status_t local_status;
+  utils::get_local_mirror_image_status(status, &local_status);
+
+  if (local_status.up) {
     r = image.mirror_image_get_instance_id(&instance_id);
     if (r == -EOPNOTSUPP) {
       std::cerr << "rbd: newer release of Ceph OSDs required to map image "
@@ -301,16 +304,17 @@ int execute_status(const po::variables_map &vm,
     }
   }
 
-  std::string state = utils::mirror_image_status_state(status);
+  std::string state = utils::mirror_image_site_status_state(local_status);
   std::string last_update = (
-    status.last_update == 0 ? "" : utils::timestr(status.last_update));
+    local_status.last_update == 0 ?
+      "" : utils::timestr(local_status.last_update));
 
   if (formatter != nullptr) {
     formatter->open_object_section("image");
     formatter->dump_string("name", image_name);
     formatter->dump_string("global_id", status.info.global_id);
     formatter->dump_string("state", state);
-    formatter->dump_string("description", status.description);
+    formatter->dump_string("description", local_status.description);
     daemon_service_info.dump(instance_id, formatter);
     formatter->dump_string("last_update", last_update);
     formatter->close_section(); // image
@@ -319,7 +323,7 @@ int execute_status(const po::variables_map &vm,
     std::cout << image_name << ":\n"
              << "  global_id:   " << status.info.global_id << "\n"
              << "  state:       " << state << "\n"
-              << "  description: " << status.description << "\n";
+              << "  description: " << local_status.description << "\n";
     if (!instance_id.empty()) {
       std::cout << "  service:     " <<
         daemon_service_info.get_description(instance_id) << "\n";
index 941d1e57572fd683206e1eec2aead03235be2a8f..1c85f8d960d57dcfe34f4dbc2d2b55a9954aa588 100644 (file)
@@ -186,7 +186,7 @@ int get_remote_cluster_spec(const po::variables_map &vm,
 int set_peer_config_key(librados::IoCtx& io_ctx, const std::string& peer_uuid,
                         std::map<std::string, std::string>&& attributes) {
   librbd::RBD rbd;
-  int r = rbd.mirror_peer_set_attributes(io_ctx, peer_uuid, attributes);
+  int r = rbd.mirror_peer_site_set_attributes(io_ctx, peer_uuid, attributes);
   if (r == -EPERM) {
     std::cerr << "rbd: permission denied attempting to set peer "
               << "config-key secrets in the monitor" << std::endl;
@@ -202,7 +202,7 @@ int set_peer_config_key(librados::IoCtx& io_ctx, const std::string& peer_uuid,
 int get_peer_config_key(librados::IoCtx& io_ctx, const std::string& peer_uuid,
                         std::map<std::string, std::string>* attributes) {
   librbd::RBD rbd;
-  int r = rbd.mirror_peer_get_attributes(io_ctx, peer_uuid, attributes);
+  int r = rbd.mirror_peer_site_get_attributes(io_ctx, peer_uuid, attributes);
   if (r == -ENOENT) {
     return r;
   } else if (r == -EPERM) {
@@ -243,7 +243,7 @@ int update_peer_config_key(librados::IoCtx& io_ctx,
 
 int format_mirror_peers(librados::IoCtx& io_ctx,
                         at::Format::Formatter formatter,
-                        const std::vector<librbd::mirror_peer_t> &peers,
+                        const std::vector<librbd::mirror_peer_site_t> &peers,
                         bool config_key) {
   TextTable tbl;
   if (formatter != nullptr) {
@@ -276,7 +276,7 @@ int format_mirror_peers(librados::IoCtx& io_ctx,
     if (formatter != nullptr) {
       formatter->open_object_section("peer");
       formatter->dump_string("uuid", peer.uuid);
-      formatter->dump_string("cluster_name", peer.cluster_name);
+      formatter->dump_string("cluster_name", peer.site_name);
       formatter->dump_string("client_name", peer.client_name);
       for (auto& pair : attributes) {
         formatter->dump_string(pair.first.c_str(), pair.second);
@@ -285,7 +285,7 @@ int format_mirror_peers(librados::IoCtx& io_ctx,
     } else {
       tbl << " "
           << peer.uuid
-          << peer.cluster_name
+          << peer.site_name
           << peer.client_name;
       if (config_key) {
         tbl << attributes["mon_host"]
@@ -580,41 +580,44 @@ protected:
   void execute_action(librbd::Image &image,
                       librbd::RBD::AioCompletion *aio_comp) override {
     image.get_id(&m_image_id);
-    image.aio_mirror_image_get_status(&m_mirror_image_status,
-                                      sizeof(m_mirror_image_status), aio_comp);
+    image.aio_mirror_image_get_global_status(
+      &m_mirror_image_global_status, sizeof(m_mirror_image_global_status),
+      aio_comp);
   }
 
   void finalize_action() override {
-    if (m_mirror_image_status.info.global_id.empty()) {
+    if (m_mirror_image_global_status.info.global_id.empty()) {
       return;
     }
 
-    std::string state = utils::mirror_image_status_state(m_mirror_image_status);
-    std::string instance_id = (m_mirror_image_status.up &&
+    librbd::mirror_image_site_status_t local_status;
+    utils::get_local_mirror_image_status(
+      m_mirror_image_global_status, &local_status);
+
+    std::string state = utils::mirror_image_site_status_state(local_status);
+    std::string instance_id = (local_status.up &&
                                m_instance_ids.count(m_image_id)) ?
         m_instance_ids.find(m_image_id)->second : "";
     std::string last_update = (
-      m_mirror_image_status.last_update == 0 ?
-        "" : utils::timestr(m_mirror_image_status.last_update));
+      local_status.last_update == 0 ?
+        "" : utils::timestr(local_status.last_update));
 
     if (m_formatter != nullptr) {
       m_formatter->open_object_section("image");
-      m_formatter->dump_string("name", m_mirror_image_status.name);
-      m_formatter->dump_string("global_id",
-                               m_mirror_image_status.info.global_id);
+      m_formatter->dump_string("name", m_mirror_image_global_status.name);
+      m_formatter->dump_string(
+        "global_id", m_mirror_image_global_status.info.global_id);
       m_formatter->dump_string("state", state);
-      m_formatter->dump_string("description",
-                               m_mirror_image_status.description);
+      m_formatter->dump_string("description", local_status.description);
       m_daemon_service_info.dump(instance_id, m_formatter);
       m_formatter->dump_string("last_update", last_update);
       m_formatter->close_section(); // image
     } else {
-      std::cout << "\n" << m_mirror_image_status.name << ":\n"
+      std::cout << "\n" << m_mirror_image_global_status.name << ":\n"
                << "  global_id:   "
-                << m_mirror_image_status.info.global_id << "\n"
+                << m_mirror_image_global_status.info.global_id << "\n"
                << "  state:       " << state << "\n"
-               << "  description: "
-                << m_mirror_image_status.description << "\n";
+               << "  description: " << local_status.description << "\n";
       if (!instance_id.empty()) {
         std::cout << "  service:     "
                   << m_daemon_service_info.get_description(instance_id) << "\n";
@@ -632,7 +635,7 @@ private:
   const MirrorDaemonServiceInfo &m_daemon_service_info;
   at::Format::Formatter m_formatter;
   std::string m_image_id;
-  librbd::mirror_image_status_t m_mirror_image_status;
+  librbd::mirror_image_global_status_t m_mirror_image_global_status;
 };
 
 template <typename RequestT>
@@ -887,8 +890,8 @@ int execute_peer_add(const po::variables_map &vm,
   // TODO: temporary restriction to prevent adding multiple peers
   // until rbd-mirror daemon can properly handle the scenario
   librbd::RBD rbd;
-  std::vector<librbd::mirror_peer_t> mirror_peers;
-  r = rbd.mirror_peer_list(io_ctx, &mirror_peers);
+  std::vector<librbd::mirror_peer_site_t> mirror_peers;
+  r = rbd.mirror_peer_site_list(io_ctx, &mirror_peers);
   if (r < 0) {
     std::cerr << "rbd: failed to list mirror peers" << std::endl;
     return r;
@@ -899,7 +902,9 @@ int execute_peer_add(const po::variables_map &vm,
   }
 
   std::string uuid;
-  r = rbd.mirror_peer_add(io_ctx, &uuid, remote_cluster, remote_client_name);
+  r = rbd.mirror_peer_site_add(
+    io_ctx, &uuid, RBD_MIRROR_PEER_DIRECTION_RX_TX, remote_cluster,
+    remote_client_name);
   if (r < 0) {
     std::cerr << "rbd: error adding mirror peer" << std::endl;
     return r;
@@ -951,7 +956,7 @@ int execute_peer_remove(const po::variables_map &vm,
   }
 
   librbd::RBD rbd;
-  r = rbd.mirror_peer_remove(io_ctx, uuid);
+  r = rbd.mirror_peer_site_remove(io_ctx, uuid);
   if (r < 0) {
     std::cerr << "rbd: error removing mirror peer" << std::endl;
     return r;
@@ -1026,9 +1031,10 @@ int execute_peer_set(const po::variables_map &vm,
 
   librbd::RBD rbd;
   if (key == "client") {
-    r = rbd.mirror_peer_set_client(io_ctx, uuid.c_str(), value.c_str());
+    r = rbd.mirror_peer_site_set_client_name(io_ctx, uuid.c_str(),
+                                             value.c_str());
   } else if (key == "cluster") {
-    r = rbd.mirror_peer_set_cluster(io_ctx, uuid.c_str(), value.c_str());
+    r = rbd.mirror_peer_site_set_name(io_ctx, uuid.c_str(), value.c_str());
   } else {
     r = update_peer_config_key(io_ctx, uuid, key, value);
     if (r  == -ENOENT) {
@@ -1211,9 +1217,9 @@ int execute_info(const po::variables_map &vm,
     return r;
   }
 
-  std::vector<librbd::mirror_peer_t> mirror_peers;
+  std::vector<librbd::mirror_peer_site_t> mirror_peers;
   if (namespace_name.empty()) {
-    r = rbd.mirror_peer_list(io_ctx, &mirror_peers);
+    r = rbd.mirror_peer_site_list(io_ctx, &mirror_peers);
     if (r < 0) {
       return r;
     }
index 3d381f3c9b182f63c58643402835b61eef9155c2..b69475e04af8aa3843a671e6a7b8ba4f8c7d241c 100644 (file)
@@ -140,8 +140,8 @@ void ClusterWatcher::read_pool_peers(PoolPeers *pool_peers)
       continue;
     }
 
-    vector<librbd::mirror_peer_t> configs;
-    r = librbd::api::Mirror<>::peer_list(ioctx, &configs);
+    vector<librbd::mirror_peer_site_t> configs;
+    r = librbd::api::Mirror<>::peer_site_list(ioctx, &configs);
     if (r < 0) {
       derr << "error reading mirroring config for pool " << pool_name
           << cpp_strerror(r) << dendl;
@@ -153,7 +153,7 @@ void ClusterWatcher::read_pool_peers(PoolPeers *pool_peers)
 
     std::vector<PeerSpec> peers{configs.begin(), configs.end()};
     for (auto& peer : peers) {
-      r = resolve_peer_config_keys(pool_id, pool_name, &peer);
+      r = resolve_peer_site_config_keys(pool_id, pool_name, &peer);
       if (r < 0) {
         break;
       }
@@ -183,9 +183,9 @@ int ClusterWatcher::read_site_name(std::string* site_name) {
   return rbd.mirror_site_name_get(*m_cluster, site_name);
 }
 
-int ClusterWatcher::resolve_peer_config_keys(int64_t pool_id,
-                                             const std::string& pool_name,
-                                             PeerSpec* peer) {
+int ClusterWatcher::resolve_peer_site_config_keys(int64_t pool_id,
+                                                  const std::string& pool_name,
+                                                  PeerSpec* peer) {
   dout(10) << "retrieving config-key: pool_id=" << pool_id << ", "
            << "pool_name=" << pool_name << ", "
            << "peer_uuid=" << peer->uuid << dendl;
index ae3f210e07f7f59e6d50bdfc5dcba3743e332ff0..93356fec6b199aa4dc12bab990f4fbb237820857 100644 (file)
@@ -63,8 +63,8 @@ private:
 
   int read_site_name(std::string* site_name);
 
-  int resolve_peer_config_keys(int64_t pool_id, const std::string& pool_name,
-                               PeerSpec* peer);
+  int resolve_peer_site_config_keys(
+      int64_t pool_id, const std::string& pool_name, PeerSpec* peer);
 };
 
 } // namespace mirror
index edce547daeb7c289afd5b462e295f5e45a59f8d9..ab3146eb420e1a2335027b7e298deaf9296fa6f8 100644 (file)
@@ -81,9 +81,9 @@ struct PeerSpec {
     : uuid(uuid), cluster_name(cluster_name), client_name(client_name)
   {
   }
-  PeerSpec(const librbd::mirror_peer_t &peer) :
+  PeerSpec(const librbd::mirror_peer_site_t &peer) :
     uuid(peer.uuid),
-    cluster_name(peer.cluster_name),
+    cluster_name(peer.site_name),
     client_name(peer.client_name)
   {
   }