namespace at = argument_types;
namespace po = boost::program_options;
+static const std::string JOURNAL_SPEC("journal-spec");
+static const std::string JOURNAL_NAME("journal");
+static const std::string DEST_JOURNAL_NAME("dest-journal");
+
+void add_journal_option(po::options_description *opt,
+ at::ArgumentModifier modifier) {
+ std::string name = JOURNAL_NAME;
+ std::string description = at::get_description_prefix(modifier) +
+ "journal name";
+ switch (modifier) {
+ case at::ARGUMENT_MODIFIER_NONE:
+ case at::ARGUMENT_MODIFIER_SOURCE:
+ break;
+ case at::ARGUMENT_MODIFIER_DEST:
+ name = DEST_JOURNAL_NAME;
+ break;
+ }
+
+ // TODO add validator
+ opt->add_options()
+ (name.c_str(), po::value<std::string>(), description.c_str());
+}
+
+void add_journal_spec_options(po::options_description *pos,
+ po::options_description *opt,
+ at::ArgumentModifier modifier) {
+
+ pos->add_options()
+ ((get_name_prefix(modifier) + JOURNAL_SPEC).c_str(),
+ (get_description_prefix(modifier) + "journal specification\n" +
+ "(example: [<pool-name>/[<namespace>/]]<journal-name>)").c_str());
+ add_pool_option(opt, modifier);
+ add_namespace_option(opt, modifier);
+ add_image_option(opt, modifier);
+ add_journal_option(opt, modifier);
+}
+
+int get_pool_journal_names(const po::variables_map &vm,
+ at::ArgumentModifier mod,
+ size_t *spec_arg_index,
+ std::string *pool_name,
+ std::string *namespace_name,
+ std::string *journal_name) {
+ std::string pool_key = (mod == at::ARGUMENT_MODIFIER_DEST ?
+ at::DEST_POOL_NAME : at::POOL_NAME);
+ std::string namespace_key = (mod == at::ARGUMENT_MODIFIER_DEST ?
+ at::DEST_NAMESPACE_NAME : at::NAMESPACE_NAME);
+ std::string image_key = (mod == at::ARGUMENT_MODIFIER_DEST ?
+ at::DEST_IMAGE_NAME : at::IMAGE_NAME);
+ std::string journal_key = (mod == at::ARGUMENT_MODIFIER_DEST ?
+ DEST_JOURNAL_NAME : JOURNAL_NAME);
+
+ if (vm.count(pool_key) && pool_name != nullptr) {
+ *pool_name = vm[pool_key].as<std::string>();
+ }
+ if (vm.count(namespace_key) && namespace_name != nullptr) {
+ *namespace_name = vm[namespace_key].as<std::string>();
+ }
+ if (vm.count(journal_key) && journal_name != nullptr) {
+ *journal_name = vm[journal_key].as<std::string>();
+ }
+
+ std::string image_name;
+ if (vm.count(image_key)) {
+ image_name = vm[image_key].as<std::string>();
+ }
+
+ int r;
+ if (journal_name != nullptr && !journal_name->empty()) {
+ // despite the separate pool option,
+ // we can also specify them via the journal option
+ std::string journal_name_copy(*journal_name);
+ r = extract_spec(journal_name_copy, pool_name, namespace_name, journal_name,
+ nullptr, utils::SPEC_VALIDATION_FULL);
+ if (r < 0) {
+ return r;
+ }
+ }
+
+ if (!image_name.empty()) {
+ // despite the separate pool option,
+ // we can also specify them via the image option
+ std::string image_name_copy(image_name);
+ r = extract_spec(image_name_copy, pool_name, namespace_name, &image_name,
+ nullptr, utils::SPEC_VALIDATION_NONE);
+ if (r < 0) {
+ return r;
+ }
+ }
+
+ if (journal_name != nullptr && spec_arg_index != nullptr &&
+ journal_name->empty()) {
+ std::string spec = utils::get_positional_argument(vm, (*spec_arg_index)++);
+ if (!spec.empty()) {
+ r = extract_spec(spec, pool_name, namespace_name, journal_name, nullptr,
+ utils::SPEC_VALIDATION_FULL);
+ if (r < 0) {
+ return r;
+ }
+ }
+ }
+
+ if (pool_name != nullptr && pool_name->empty()) {
+ *pool_name = utils::get_default_pool_name();
+ }
+
+ if (pool_name != nullptr && namespace_name != nullptr &&
+ journal_name != nullptr && journal_name->empty() && !image_name.empty()) {
+ // Try to get journal name from image info.
+ librados::Rados rados;
+ librados::IoCtx io_ctx;
+ librbd::Image image;
+ int r = utils::init_and_open_image(*pool_name, *namespace_name, image_name,
+ "", "", true, &rados, &io_ctx, &image);
+ if (r < 0) {
+ std::cerr << "rbd: failed to open image " << image_name
+ << " to get journal name: " << cpp_strerror(r) << std::endl;
+ return r;
+ }
+
+ uint64_t features;
+ r = image.features(&features);
+ if (r < 0) {
+ return r;
+ }
+ if ((features & RBD_FEATURE_JOURNALING) == 0) {
+ std::cerr << "rbd: journaling is not enabled for image " << image_name
+ << std::endl;
+ return -EINVAL;
+ }
+ *journal_name = utils::image_id(image);
+ }
+
+ if (journal_name != nullptr && journal_name->empty()) {
+ std::string prefix = at::get_description_prefix(mod);
+ std::cerr << "rbd: "
+ << (mod == at::ARGUMENT_MODIFIER_DEST ? prefix : std::string())
+ << "journal was not specified" << std::endl;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int do_show_journal_info(librados::Rados& rados, librados::IoCtx& io_ctx,
const std::string& journal_id, Formatter *f)
{
librbd::journal::EventEntry& event_entry,
bool verbose) {
try {
- bufferlist::iterator it = data.begin();
- ::decode(event_entry, it);
+ auto it = data.cbegin();
+ decode(event_entry, it);
} catch (const buffer::error &err) {
std::cerr << "failed to decode event entry: " << err.what() << std::endl;
return -EINVAL;
}
bool read_entry(bufferlist& bl, int& r) {
- // Entries are storead in the file using the following format:
+ // Entries are stored in the file using the following format:
//
// # Optional comments
// NNN {json encoded entry}
<< std::endl;
return false;
}
- assert(entry_size > 0);
+ ceph_assert(entry_size > 0);
// Read entry.
r = bl.read_fd(m_fd, entry_size);
if (r < 0) {
return false;
}
if (r != entry_size) {
- std::cerr << "rbd: error reading from stdin: trucated"
+ std::cerr << "rbd: error reading from stdin: truncated"
<< std::endl;
r = -EINVAL;
return false;
if (r < 0) {
return r;
}
- m_journaler.start_append(0, 0, 0);
+ m_journaler.start_append(0, 0, 0, 0);
int r1 = 0;
bufferlist bl;
void get_info_arguments(po::options_description *positional,
po::options_description *options) {
- at::add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
+ add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
at::add_format_options(options);
}
-int execute_info(const po::variables_map &vm) {
+int execute_info(const po::variables_map &vm,
+ const std::vector<std::string> &ceph_global_init_args) {
size_t arg_index = 0;
std::string pool_name;
+ std::string namespace_name;
std::string journal_name;
- int r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE,
- &arg_index, &pool_name, &journal_name);
+ int r = get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE, &arg_index,
+ &pool_name, &namespace_name, &journal_name);
if (r < 0) {
return r;
}
librados::Rados rados;
librados::IoCtx io_ctx;
- r = utils::init(pool_name, &rados, &io_ctx);
+ r = utils::init(pool_name, namespace_name, &rados, &io_ctx);
if (r < 0) {
return r;
}
void get_status_arguments(po::options_description *positional,
po::options_description *options) {
- at::add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
+ add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
at::add_format_options(options);
}
-int execute_status(const po::variables_map &vm) {
+int execute_status(const po::variables_map &vm,
+ const std::vector<std::string> &ceph_global_init_args) {
size_t arg_index = 0;
std::string pool_name;
+ std::string namespace_name;
std::string journal_name;
- int r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE,
- &arg_index, &pool_name, &journal_name);
+ int r = get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE, &arg_index,
+ &pool_name, &namespace_name, &journal_name);
if (r < 0) {
return r;
}
librados::Rados rados;
librados::IoCtx io_ctx;
- r = utils::init(pool_name, &rados, &io_ctx);
+ r = utils::init(pool_name, namespace_name, &rados, &io_ctx);
if (r < 0) {
return r;
}
void get_reset_arguments(po::options_description *positional,
po::options_description *options) {
- at::add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
+ add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
}
-int execute_reset(const po::variables_map &vm) {
+int execute_reset(const po::variables_map &vm,
+ const std::vector<std::string> &ceph_global_init_args) {
size_t arg_index = 0;
std::string pool_name;
+ std::string namespace_name;
std::string journal_name;
- int r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE,
- &arg_index, &pool_name, &journal_name);
+ int r = get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE, &arg_index,
+ &pool_name, &namespace_name, &journal_name);
if (r < 0) {
return r;
}
librados::Rados rados;
librados::IoCtx io_ctx;
- r = utils::init(pool_name, &rados, &io_ctx);
+ r = utils::init(pool_name, namespace_name, &rados, &io_ctx);
if (r < 0) {
return r;
}
void get_client_disconnect_arguments(po::options_description *positional,
po::options_description *options) {
- at::add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
+ add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
options->add_options()
("client-id", po::value<std::string>(),
"client ID (or leave unspecified to disconnect all)");
}
-int execute_client_disconnect(const po::variables_map &vm) {
+int execute_client_disconnect(const po::variables_map &vm,
+ const std::vector<std::string> &ceph_global_init_args) {
size_t arg_index = 0;
std::string pool_name;
+ std::string namespace_name;
std::string journal_name;
- int r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE,
- &arg_index, &pool_name, &journal_name);
+ int r = get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE, &arg_index,
+ &pool_name, &namespace_name, &journal_name);
if (r < 0) {
return r;
}
librados::Rados rados;
librados::IoCtx io_ctx;
- r = utils::init(pool_name, &rados, &io_ctx);
+ r = utils::init(pool_name, namespace_name, &rados, &io_ctx);
if (r < 0) {
return r;
}
void get_inspect_arguments(po::options_description *positional,
po::options_description *options) {
- at::add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
+ add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
at::add_verbose_option(options);
}
-int execute_inspect(const po::variables_map &vm) {
+int execute_inspect(const po::variables_map &vm,
+ const std::vector<std::string> &ceph_global_init_args) {
size_t arg_index = 0;
std::string pool_name;
+ std::string namespace_name;
std::string journal_name;
- int r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE,
- &arg_index, &pool_name, &journal_name);
+ int r = get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE, &arg_index,
+ &pool_name, &namespace_name, &journal_name);
if (r < 0) {
return r;
}
librados::Rados rados;
librados::IoCtx io_ctx;
- r = utils::init(pool_name, &rados, &io_ctx);
+ r = utils::init(pool_name, namespace_name, &rados, &io_ctx);
if (r < 0) {
return r;
}
void get_export_arguments(po::options_description *positional,
po::options_description *options) {
- at::add_journal_spec_options(positional, options,
+ add_journal_spec_options(positional, options,
at::ARGUMENT_MODIFIER_SOURCE);
at::add_path_options(positional, options,
"export file (or '-' for stdout)");
at::add_no_error_option(options);
}
-int execute_export(const po::variables_map &vm) {
+int execute_export(const po::variables_map &vm,
+ const std::vector<std::string> &ceph_global_init_args) {
size_t arg_index = 0;
std::string pool_name;
+ std::string namespace_name;
std::string journal_name;
- int r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_SOURCE,
- &arg_index, &pool_name, &journal_name);
+ int r = get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_SOURCE, &arg_index,
+ &pool_name, &namespace_name, &journal_name);
if (r < 0) {
return r;
}
std::string path;
- r = utils::get_path(vm, utils::get_positional_argument(vm, 1), &path);
+ r = utils::get_path(vm, &arg_index, &path);
if (r < 0) {
return r;
}
librados::Rados rados;
librados::IoCtx io_ctx;
- r = utils::init(pool_name, &rados, &io_ctx);
+ r = utils::init(pool_name, namespace_name, &rados, &io_ctx);
if (r < 0) {
return r;
}
po::options_description *options) {
at::add_path_options(positional, options,
"import file (or '-' for stdin)");
- at::add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_DEST);
+ add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_DEST);
at::add_verbose_option(options);
at::add_no_error_option(options);
}
-int execute_import(const po::variables_map &vm) {
+int execute_import(const po::variables_map &vm,
+ const std::vector<std::string> &ceph_global_init_args) {
std::string path;
- int r = utils::get_path(vm, utils::get_positional_argument(vm, 0), &path);
+ size_t arg_index = 0;
+ int r = utils::get_path(vm, &arg_index, &path);
if (r < 0) {
return r;
}
- size_t arg_index = 1;
std::string pool_name;
+ std::string namespace_name;
std::string journal_name;
- r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_DEST,
- &arg_index, &pool_name, &journal_name);
+ r = get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_DEST, &arg_index,
+ &pool_name, &namespace_name, &journal_name);
if (r < 0) {
return r;
}
librados::Rados rados;
librados::IoCtx io_ctx;
- r = utils::init(pool_name, &rados, &io_ctx);
+ r = utils::init(pool_name, namespace_name, &rados, &io_ctx);
if (r < 0) {
return r;
}
r = do_import_journal(io_ctx, journal_name, path, vm[at::NO_ERROR].as<bool>(),
vm[at::VERBOSE].as<bool>());
if (r < 0) {
- std::cerr << "rbd: journal export: " << cpp_strerror(r) << std::endl;
+ std::cerr << "rbd: journal import: " << cpp_strerror(r) << std::endl;
return r;
}
return 0;