return 0;
}
+/*********************** methods for rbd_group_directory ***********************/
+
+int dir_add(cls_method_context_t hctx,
+ const string &name, const string &id,
+ bool check_for_unique_id)
+{
+ if (!name.size() || !is_valid_id(id)) {
+ CLS_ERR("invalid group name '%s' or id '%s'",
+ name.c_str(), id.c_str());
+ return -EINVAL;
+ }
+
+ CLS_LOG(20, "dir_add name=%s id=%s", name.c_str(), id.c_str());
+
+ string name_key = dir_key_for_name(name);
+ string id_key = dir_key_for_id(id);
+ string tmp;
+ int r = read_key(hctx, name_key, &tmp);
+ if (r != -ENOENT) {
+ CLS_LOG(10, "name already exists");
+ return -EEXIST;
+ }
+ r = read_key(hctx, id_key, &tmp);
+ if (r != -ENOENT && check_for_unique_id) {
+ CLS_LOG(10, "id already exists");
+ return -EBADF;
+ }
+ bufferlist id_bl, name_bl;
+ encode(id, id_bl);
+ encode(name, name_bl);
+ map<string, bufferlist> omap_vals;
+ omap_vals[name_key] = id_bl;
+ omap_vals[id_key] = name_bl;
+ return cls_cxx_map_set_vals(hctx, &omap_vals);
+}
+
+int dir_remove(cls_method_context_t hctx,
+ const string &name, const string &id)
+{
+ CLS_LOG(20, "dir_remove name=%s id=%s", name.c_str(), id.c_str());
+
+ string name_key = dir_key_for_name(name);
+ string id_key = dir_key_for_id(id);
+ string stored_name, stored_id;
+
+ int r = read_key(hctx, name_key, &stored_id);
+ if (r < 0) {
+ if (r != -ENOENT)
+ CLS_ERR("error reading name to id mapping: %s", cpp_strerror(r).c_str());
+ return r;
+ }
+ r = read_key(hctx, id_key, &stored_name);
+ if (r < 0) {
+ if (r != -ENOENT)
+ CLS_ERR("error reading id to name mapping: %s", cpp_strerror(r).c_str());
+ return r;
+ }
+
+ // check if this op raced with a rename
+ if (stored_name != name || stored_id != id) {
+ CLS_ERR("stored name '%s' and id '%s' do not match args '%s' and '%s'",
+ stored_name.c_str(), stored_id.c_str(), name.c_str(), id.c_str());
+ return -ESTALE;
+ }
+
+ r = cls_cxx_map_remove_key(hctx, name_key);
+ if (r < 0) {
+ CLS_ERR("error removing name: %s", cpp_strerror(r).c_str());
+ return r;
+ }
+
+ r = cls_cxx_map_remove_key(hctx, id_key);
+ if (r < 0) {
+ CLS_ERR("error removing id: %s", cpp_strerror(r).c_str());
+ return r;
+ }
+
+ return 0;
+}
+
/**
* List groups from the directory.
*
return -EINVAL;
}
- if (!name.size() || !is_valid_id(id)) {
- CLS_ERR("invalid group name '%s' or id '%s'",
- name.c_str(), id.c_str());
+ return dir_add(hctx, name, id, true);
+}
+
+/**
+ * Rename a group to the directory.
+ *
+ * Input:
+ * @param src original name of the group (std::string)
+ * @param dest new name of the group (std::string)
+ * @param id the id of the group (std::string)
+ *
+ * Output:
+ * @return 0 on success, negative error code on failure
+ */
+int group_dir_rename(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+ string src, dest, id;
+ try {
+ bufferlist::iterator iter = in->begin();
+ decode(src, iter);
+ decode(dest, iter);
+ decode(id, iter);
+ } catch (const buffer::error &err) {
return -EINVAL;
}
- CLS_LOG(20, "group_dir_add name=%s id=%s", name.c_str(), id.c_str());
+ int r = dir_remove(hctx, src, id);
+ if (r < 0)
+ return r;
- string tmp;
- string name_key = dir_key_for_name(name);
- string id_key = dir_key_for_id(id);
- r = read_key(hctx, name_key, &tmp);
- if (r != -ENOENT) {
- CLS_LOG(10, "name already exists");
- return -EEXIST;
- }
- r = read_key(hctx, id_key, &tmp);
- if (r != -ENOENT) {
- CLS_LOG(10, "id already exists");
- return -EBADF;
- }
- bufferlist id_bl, name_bl;
- encode(id, id_bl);
- encode(name, name_bl);
- map<string, bufferlist> omap_vals;
- omap_vals[name_key] = id_bl;
- omap_vals[id_key] = name_bl;
- return cls_cxx_map_set_vals(hctx, &omap_vals);
+ return dir_add(hctx, dest, id, false);
}
/**
return -EINVAL;
}
- CLS_LOG(20, "group_dir_remove name=%s id=%s", name.c_str(), id.c_str());
-
- string stored_name, stored_id;
- string name_key = dir_key_for_name(name);
- string id_key = dir_key_for_id(id);
-
- int r = read_key(hctx, name_key, &stored_id);
- if (r < 0) {
- if (r != -ENOENT)
- CLS_ERR("error reading name to id mapping: %s", cpp_strerror(r).c_str());
- return r;
- }
- r = read_key(hctx, id_key, &stored_name);
- if (r < 0) {
- if (r != -ENOENT)
- CLS_ERR("error reading id to name mapping: %s", cpp_strerror(r).c_str());
- return r;
- }
-
- // check if this op raced with a rename
- if (stored_name != name || stored_id != id) {
- CLS_ERR("stored name '%s' and id '%s' do not match args '%s' and '%s'",
- stored_name.c_str(), stored_id.c_str(), name.c_str(), id.c_str());
- return -ESTALE;
- }
-
- r = cls_cxx_map_remove_key(hctx, name_key);
- if (r < 0) {
- CLS_ERR("error removing name: %s", cpp_strerror(r).c_str());
- return r;
- }
-
- r = cls_cxx_map_remove_key(hctx, id_key);
- if (r < 0) {
- CLS_ERR("error removing id: %s", cpp_strerror(r).c_str());
- return r;
- }
-
- return 0;
+ return dir_remove(hctx, name, id);
}
/**
cls_method_handle_t h_group_dir_list;
cls_method_handle_t h_group_dir_add;
cls_method_handle_t h_group_dir_remove;
+ cls_method_handle_t h_group_dir_rename;
cls_method_handle_t h_group_image_remove;
cls_method_handle_t h_group_image_list;
cls_method_handle_t h_group_image_set;
cls_register_cxx_method(h_class, "group_dir_remove",
CLS_METHOD_RD | CLS_METHOD_WR,
group_dir_remove, &h_group_dir_remove);
+ cls_register_cxx_method(h_class, "group_dir_rename",
+ CLS_METHOD_RD | CLS_METHOD_WR,
+ group_dir_rename, &h_group_dir_rename);
cls_register_cxx_method(h_class, "group_image_remove",
CLS_METHOD_RD | CLS_METHOD_WR,
group_image_remove, &h_group_image_remove);
// Consistency groups functions
int group_dir_list(librados::IoCtx *ioctx, const std::string &oid,
- const std::string &start, uint64_t max_return,
- map<string, string> *cgs)
+ const std::string &start, uint64_t max_return,
+ map<string, string> *cgs)
{
bufferlist in, out;
encode(start, in);
}
int group_dir_add(librados::IoCtx *ioctx, const std::string &oid,
- const std::string &name, const std::string &id)
+ const std::string &name, const std::string &id)
{
bufferlist in, out;
encode(name, in);
return ioctx->exec(oid, "rbd", "group_dir_add", in, out);
}
+ int group_dir_rename(librados::IoCtx *ioctx, const std::string &oid,
+ const std::string &src, const std::string &dest,
+ const std::string &id)
+ {
+ bufferlist in, out;
+ encode(src, in);
+ encode(dest, in);
+ encode(id, in);
+ return ioctx->exec(oid, "rbd", "group_dir_rename", in, out);
+ }
+
int group_dir_remove(librados::IoCtx *ioctx, const std::string &oid,
- const std::string &name, const std::string &id)
+ const std::string &name, const std::string &id)
{
bufferlist in, out;
encode(name, in);
// Consistency groups functions
int group_dir_list(librados::IoCtx *ioctx, const std::string &oid,
- const std::string &start, uint64_t max_return,
- map<string, string> *groups);
+ const std::string &start, uint64_t max_return,
+ map<string, string> *groups);
int group_dir_add(librados::IoCtx *ioctx, const std::string &oid,
- const std::string &name, const std::string &id);
+ const std::string &name, const std::string &id);
+ int group_dir_rename(librados::IoCtx *ioctx, const std::string &oid,
+ const std::string &src, const std::string &dest,
+ const std::string &id);
int group_dir_remove(librados::IoCtx *ioctx, const std::string &oid,
- const std::string &name, const std::string &id);
+ const std::string &name, const std::string &id);
int group_image_remove(librados::IoCtx *ioctx, const std::string &oid,
const cls::rbd::GroupImageSpec &spec);
int group_image_list(librados::IoCtx *ioctx, const std::string &oid,
ASSERT_EQ(-EEXIST, group_dir_add(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
}
+TEST_F(TestClsRbd, group_dir_rename) {
+ librados::IoCtx ioctx;
+ ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
+ ioctx.remove(RBD_GROUP_DIRECTORY);
+
+ string group_id = "cgid";
+ string src_name = "cgnamesrc";
+ string dest_name = "cgnamedest";
+ add_group_to_dir(ioctx, group_id, src_name);
+
+ ASSERT_EQ(0, group_dir_rename(&ioctx, RBD_GROUP_DIRECTORY,
+ src_name, dest_name, group_id));
+ map<string, string> cgs;
+ ASSERT_EQ(0, group_dir_list(&ioctx, RBD_GROUP_DIRECTORY, "", 10, &cgs));
+ ASSERT_EQ(1U, cgs.size());
+ auto it = cgs.begin();
+ ASSERT_EQ(group_id, it->second);
+ ASSERT_EQ(dest_name, it->first);
+
+ // destination group name existing
+ ASSERT_EQ(-EEXIST, group_dir_rename(&ioctx, RBD_GROUP_DIRECTORY,
+ dest_name, dest_name, group_id));
+ ASSERT_EQ(0, group_dir_remove(&ioctx, RBD_GROUP_DIRECTORY, dest_name, group_id));
+ // source group name missing
+ ASSERT_EQ(-ENOENT, group_dir_rename(&ioctx, RBD_GROUP_DIRECTORY,
+ dest_name, src_name, group_id));
+}
+
TEST_F(TestClsRbd, group_dir_remove) {
librados::IoCtx ioctx;
ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));