X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ftools%2Frbd%2Faction%2FJournal.cc;fp=src%2Fceph%2Fsrc%2Ftools%2Frbd%2Faction%2FJournal.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=3485dc1f975a5da68517c615549b6a5f2250483f;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/tools/rbd/action/Journal.cc b/src/ceph/src/tools/rbd/action/Journal.cc deleted file mode 100644 index 3485dc1..0000000 --- a/src/ceph/src/tools/rbd/action/Journal.cc +++ /dev/null @@ -1,1096 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#include "tools/rbd/ArgumentTypes.h" -#include "tools/rbd/Shell.h" -#include "tools/rbd/Utils.h" -#include "common/Cond.h" -#include "common/Formatter.h" -#include "common/ceph_json.h" -#include "common/errno.h" -#include "common/safe_io.h" -#include "include/stringify.h" -#include -#include -#include -#include "cls/rbd/cls_rbd_client.h" -#include "cls/journal/cls_journal_types.h" -#include "cls/journal/cls_journal_client.h" - -#include "journal/Journaler.h" -#include "journal/ReplayEntry.h" -#include "journal/ReplayHandler.h" -#include "journal/Settings.h" -#include "librbd/journal/Types.h" - -namespace rbd { -namespace action { -namespace journal { - -namespace at = argument_types; -namespace po = boost::program_options; - -static int do_show_journal_info(librados::Rados& rados, librados::IoCtx& io_ctx, - const std::string& journal_id, Formatter *f) -{ - int r; - C_SaferCond cond; - - std::string header_oid = ::journal::Journaler::header_oid(journal_id); - std::string object_oid_prefix = ::journal::Journaler::object_oid_prefix( - io_ctx.get_id(), journal_id); - uint8_t order; - uint8_t splay_width; - int64_t pool_id; - - cls::journal::client::get_immutable_metadata(io_ctx, header_oid, &order, - &splay_width, &pool_id, &cond); - r = cond.wait(); - if (r < 0) { - std::cerr << "failed to get journal metadata: " << cpp_strerror(r) - << std::endl; - return r; - } - - std::string object_pool_name; - if (pool_id >= 0) { - r = rados.pool_reverse_lookup(pool_id, &object_pool_name); - if (r < 0) { - std::cerr << "error looking up pool name for pool_id=" << pool_id << ": " - << cpp_strerror(r) << std::endl; - } - } - - if (f) { - f->open_object_section("journal"); - f->dump_string("journal_id", journal_id); - f->dump_string("header_oid", header_oid); - f->dump_string("object_oid_prefix", object_oid_prefix); - f->dump_int("order", order); - f->dump_int("splay_width", splay_width); - if (!object_pool_name.empty()) { - f->dump_string("object_pool", object_pool_name); - } - f->close_section(); - f->flush(std::cout); - } else { - std::cout << "rbd journal '" << journal_id << "':" << std::endl; - std::cout << "\theader_oid: " << header_oid << std::endl; - std::cout << "\tobject_oid_prefix: " << object_oid_prefix << std::endl; - std::cout << "\torder: " << static_cast(order) << " (" - << prettybyte_t(1ull << order) << " objects)"<< std::endl; - std::cout << "\tsplay_width: " << static_cast(splay_width) << std::endl; - if (!object_pool_name.empty()) { - std::cout << "\tobject_pool: " << object_pool_name << std::endl; - } - } - return 0; -} - -static int do_show_journal_status(librados::IoCtx& io_ctx, - const std::string& journal_id, Formatter *f) -{ - int r; - - C_SaferCond cond; - uint64_t minimum_set; - uint64_t active_set; - std::set registered_clients; - std::string oid = ::journal::Journaler::header_oid(journal_id); - - cls::journal::client::get_mutable_metadata(io_ctx, oid, &minimum_set, - &active_set, ®istered_clients, - &cond); - r = cond.wait(); - if (r < 0) { - std::cerr << "warning: failed to get journal metadata" << std::endl; - return r; - } - - if (f) { - f->open_object_section("status"); - f->dump_unsigned("minimum_set", minimum_set); - f->dump_unsigned("active_set", active_set); - f->open_array_section("registered_clients"); - for (std::set::iterator c = - registered_clients.begin(); c != registered_clients.end(); ++c) { - f->open_object_section("client"); - c->dump(f); - f->close_section(); - } - f->close_section(); - f->close_section(); - f->flush(std::cout); - } else { - std::cout << "minimum_set: " << minimum_set << std::endl; - std::cout << "active_set: " << active_set << std::endl; - std::cout << "registered clients: " << std::endl; - for (std::set::iterator c = - registered_clients.begin(); c != registered_clients.end(); ++c) { - std::cout << "\t" << *c << std::endl; - } - } - return 0; -} - -static int do_reset_journal(librados::IoCtx& io_ctx, - const std::string& journal_id) -{ - // disable/re-enable journaling to delete/re-create the journal - // to properly handle mirroring constraints - std::string image_name; - int r = librbd::cls_client::dir_get_name(&io_ctx, RBD_DIRECTORY, journal_id, - &image_name); - if (r < 0) { - std::cerr << "failed to locate journal's image: " << cpp_strerror(r) - << std::endl; - return r; - } - - librbd::Image image; - r = utils::open_image(io_ctx, image_name, false, &image); - if (r < 0) { - std::cerr << "failed to open image: " << cpp_strerror(r) << std::endl; - return r; - } - - r = image.update_features(RBD_FEATURE_JOURNALING, false); - if (r < 0) { - std::cerr << "failed to disable image journaling: " << cpp_strerror(r) - << std::endl; - return r; - } - - r = image.update_features(RBD_FEATURE_JOURNALING, true); - if (r < 0) { - std::cerr << "failed to re-enable image journaling: " << cpp_strerror(r) - << std::endl; - return r; - } - return 0; -} - -static int do_disconnect_journal_client(librados::IoCtx& io_ctx, - const std::string& journal_id, - const std::string& client_id) -{ - int r; - - C_SaferCond cond; - uint64_t minimum_set; - uint64_t active_set; - std::set registered_clients; - std::string oid = ::journal::Journaler::header_oid(journal_id); - - cls::journal::client::get_mutable_metadata(io_ctx, oid, &minimum_set, - &active_set, ®istered_clients, - &cond); - r = cond.wait(); - if (r < 0) { - std::cerr << "warning: failed to get journal metadata" << std::endl; - return r; - } - - static const std::string IMAGE_CLIENT_ID(""); - - bool found = false; - for (auto &c : registered_clients) { - if (c.id == IMAGE_CLIENT_ID || (!client_id.empty() && client_id != c.id)) { - continue; - } - r = cls::journal::client::client_update_state(io_ctx, oid, c.id, - cls::journal::CLIENT_STATE_DISCONNECTED); - if (r < 0) { - std::cerr << "warning: failed to disconnect client " << c.id << ": " - << cpp_strerror(r) << std::endl; - return r; - } - std::cout << "client " << c.id << " disconnected" << std::endl; - found = true; - } - - if (!found) { - if (!client_id.empty()) { - std::cerr << "warning: client " << client_id << " is not registered" - << std::endl; - } else { - std::cerr << "no registered clients to disconnect" << std::endl; - } - return -ENOENT; - } - - bufferlist bl; - r = io_ctx.notify2(oid, bl, 5000, NULL); - if (r < 0) { - std::cerr << "warning: failed to notify state change:" << ": " - << cpp_strerror(r) << std::endl; - return r; - } - - return 0; -} - -class Journaler : public ::journal::Journaler { -public: - Journaler(librados::IoCtx& io_ctx, const std::string& journal_id, - const std::string &client_id) : - ::journal::Journaler(io_ctx, journal_id, client_id, {}) { - } - - int init() { - int r; - - // TODO register with librbd payload - r = register_client(bufferlist()); - if (r < 0) { - std::cerr << "failed to register client: " << cpp_strerror(r) - << std::endl; - return r; - } - - C_SaferCond cond; - - ::journal::Journaler::init(&cond); - r = cond.wait(); - if (r < 0) { - std::cerr << "failed to initialize journal: " << cpp_strerror(r) - << std::endl; - (void) unregister_client(); - return r; - } - - return 0; - } - - int shut_down() { - int r = unregister_client(); - if (r < 0) { - std::cerr << "rbd: failed to unregister journal client: " - << cpp_strerror(r) << std::endl; - } - ::journal::Journaler::shut_down(); - - return r; - } -}; - -class JournalPlayer { -public: - JournalPlayer(librados::IoCtx& io_ctx, const std::string& journal_id, - const std::string &client_id) : - m_journaler(io_ctx, journal_id, client_id), - m_cond(), - m_r(0) { - } - - virtual ~JournalPlayer() {} - - virtual int exec() { - int r; - - r = m_journaler.init(); - if (r < 0) { - return r; - } - - ReplayHandler replay_handler(this); - - m_journaler.start_replay(&replay_handler); - - r = m_cond.wait(); - if (r < 0) { - std::cerr << "rbd: failed to process journal: " << cpp_strerror(r) - << std::endl; - if (m_r == 0) { - m_r = r; - } - } - return m_r; - } - - int shut_down() { - return m_journaler.shut_down(); - } - -protected: - struct ReplayHandler : public ::journal::ReplayHandler { - JournalPlayer *journal; - explicit ReplayHandler(JournalPlayer *_journal) : journal(_journal) {} - - void get() override {} - void put() override {} - - void handle_entries_available() override { - journal->handle_replay_ready(); - } - void handle_complete(int r) override { - journal->handle_replay_complete(r); - } - }; - - void handle_replay_ready() { - int r = 0; - while (true) { - ::journal::ReplayEntry replay_entry; - uint64_t tag_id; - if (!m_journaler.try_pop_front(&replay_entry, &tag_id)) { - break; - } - - r = process_entry(replay_entry, tag_id); - if (r < 0) { - break; - } - } - } - - virtual int process_entry(::journal::ReplayEntry replay_entry, - uint64_t tag_id) = 0; - - void handle_replay_complete(int r) { - if (m_r == 0 && r < 0) { - m_r = r; - } - m_journaler.stop_replay(&m_cond); - } - - Journaler m_journaler; - C_SaferCond m_cond; - int m_r; -}; - -static int inspect_entry(bufferlist& data, - librbd::journal::EventEntry& event_entry, - bool verbose) { - try { - bufferlist::iterator it = data.begin(); - ::decode(event_entry, it); - } catch (const buffer::error &err) { - std::cerr << "failed to decode event entry: " << err.what() << std::endl; - return -EINVAL; - } - if (verbose) { - JSONFormatter f(true); - f.open_object_section("event_entry"); - event_entry.dump(&f); - f.close_section(); - f.flush(std::cout); - } - return 0; -} - -class JournalInspector : public JournalPlayer { -public: - JournalInspector(librados::IoCtx& io_ctx, const std::string& journal_id, - bool verbose) : - JournalPlayer(io_ctx, journal_id, "INSPECT"), - m_verbose(verbose), - m_s() { - } - - int exec() override { - int r = JournalPlayer::exec(); - m_s.print(); - return r; - } - -private: - struct Stats { - Stats() : total(0), error(0) {} - - void print() { - std::cout << "Summary:" << std::endl - << " " << total << " entries inspected, " << error << " errors" - << std::endl; - } - - int total; - int error; - }; - - int process_entry(::journal::ReplayEntry replay_entry, - uint64_t tag_id) override { - m_s.total++; - if (m_verbose) { - std::cout << "Entry: tag_id=" << tag_id << ", commit_tid=" - << replay_entry.get_commit_tid() << std::endl; - } - bufferlist data = replay_entry.get_data(); - librbd::journal::EventEntry event_entry; - int r = inspect_entry(data, event_entry, m_verbose); - if (r < 0) { - m_r = r; - m_s.error++; - } - return 0; - } - - bool m_verbose; - Stats m_s; -}; - -static int do_inspect_journal(librados::IoCtx& io_ctx, - const std::string& journal_id, - bool verbose) { - JournalInspector inspector(io_ctx, journal_id, verbose); - int r = inspector.exec(); - if (r < 0) { - inspector.shut_down(); - return r; - } - - r = inspector.shut_down(); - if (r < 0) { - return r; - } - return 0; -} - -struct ExportEntry { - uint64_t tag_id; - uint64_t commit_tid; - int type; - bufferlist entry; - - ExportEntry() : tag_id(0), commit_tid(0), type(0), entry() {} - - ExportEntry(uint64_t tag_id, uint64_t commit_tid, int type, - const bufferlist& entry) - : tag_id(tag_id), commit_tid(commit_tid), type(type), entry(entry) { - } - - void dump(Formatter *f) const { - ::encode_json("tag_id", tag_id, f); - ::encode_json("commit_tid", commit_tid, f); - ::encode_json("type", type, f); - ::encode_json("entry", entry, f); - } - - void decode_json(JSONObj *obj) { - JSONDecoder::decode_json("tag_id", tag_id, obj); - JSONDecoder::decode_json("commit_tid", commit_tid, obj); - JSONDecoder::decode_json("type", type, obj); - JSONDecoder::decode_json("entry", entry, obj); - } -}; - -class JournalExporter : public JournalPlayer { -public: - JournalExporter(librados::IoCtx& io_ctx, const std::string& journal_id, - int fd, bool no_error, bool verbose) : - JournalPlayer(io_ctx, journal_id, "EXPORT"), - m_journal_id(journal_id), - m_fd(fd), - m_no_error(no_error), - m_verbose(verbose), - m_s() { - } - - int exec() override { - std::string header("# journal_id: " + m_journal_id + "\n"); - int r; - r = safe_write(m_fd, header.c_str(), header.size()); - if (r < 0) { - std::cerr << "rbd: failed to write to export file: " << cpp_strerror(r) - << std::endl; - return r; - } - r = JournalPlayer::exec(); - m_s.print(); - return r; - } - -private: - struct Stats { - Stats() : total(0), error(0) {} - - void print() { - std::cout << total << " entries processed, " << error << " errors" - << std::endl; - } - - int total; - int error; - }; - - int process_entry(::journal::ReplayEntry replay_entry, - uint64_t tag_id) override { - m_s.total++; - int type = -1; - bufferlist entry = replay_entry.get_data(); - librbd::journal::EventEntry event_entry; - int r = inspect_entry(entry, event_entry, m_verbose); - if (r < 0) { - m_s.error++; - m_r = r; - return m_no_error ? 0 : r; - } else { - type = event_entry.get_event_type(); - } - ExportEntry export_entry(tag_id, replay_entry.get_commit_tid(), type, - entry); - JSONFormatter f; - ::encode_json("event_entry", export_entry, &f); - std::ostringstream oss; - f.flush(oss); - std::string objstr = oss.str(); - std::string header = stringify(objstr.size()) + " "; - r = safe_write(m_fd, header.c_str(), header.size()); - if (r == 0) { - r = safe_write(m_fd, objstr.c_str(), objstr.size()); - } - if (r == 0) { - r = safe_write(m_fd, "\n", 1); - } - if (r < 0) { - std::cerr << "rbd: failed to write to export file: " << cpp_strerror(r) - << std::endl; - m_s.error++; - return r; - } - return 0; - } - - std::string m_journal_id; - int m_fd; - bool m_no_error; - bool m_verbose; - Stats m_s; -}; - -static int do_export_journal(librados::IoCtx& io_ctx, - const std::string& journal_id, - const std::string& path, - bool no_error, bool verbose) { - int r; - int fd; - bool to_stdout = path == "-"; - if (to_stdout) { - fd = STDOUT_FILENO; - } else { - fd = open(path.c_str(), O_WRONLY | O_CREAT | O_EXCL, 0644); - if (fd < 0) { - r = -errno; - std::cerr << "rbd: error creating " << path << std::endl; - return r; - } -#ifdef HAVE_POSIX_FADVISE - posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); -#endif - } - - JournalExporter exporter(io_ctx, journal_id, fd, no_error, verbose); - r = exporter.exec(); - - if (!to_stdout) { - close(fd); - } - - int shut_down_r = exporter.shut_down(); - if (r == 0 && shut_down_r < 0) { - r = shut_down_r; - } - - return r; -} - -class JournalImporter { -public: - JournalImporter(librados::IoCtx& io_ctx, const std::string& journal_id, - int fd, bool no_error, bool verbose) : - m_journaler(io_ctx, journal_id, "IMPORT"), - m_fd(fd), - m_no_error(no_error), - m_verbose(verbose) { - } - - bool read_entry(bufferlist& bl, int& r) { - // Entries are storead in the file using the following format: - // - // # Optional comments - // NNN {json encoded entry} - // ... - // - // Where NNN is the encoded entry size. - bl.clear(); - char buf[80]; - // Skip line feed and comments (lines started with #). - while ((r = safe_read_exact(m_fd, buf, 1)) == 0) { - if (buf[0] == '\n') { - continue; - } else if (buf[0] == '#') { - while ((r = safe_read_exact(m_fd, buf, 1)) == 0) { - if (buf[0] == '\n') { - break; - } - } - } else { - break; - } - } - if (r < 0) { - if (r == -EDOM) { - r = 0; - } - return false; - } - // Read entry size to buf. - if (!isdigit(buf[0])) { - r = -EINVAL; - std::cerr << "rbd: import data invalid format (digit expected)" - << std::endl; - return false; - } - for (size_t i = 1; i < sizeof(buf); i++) { - r = safe_read_exact(m_fd, buf + i, 1); - if (r < 0) { - std::cerr << "rbd: error reading import data" << std::endl; - return false; - } - if (!isdigit(buf[i])) { - if (buf[i] != ' ') { - r = -EINVAL; - std::cerr << "rbd: import data invalid format (space expected)" - << std::endl; - return false; - } - buf[i] = '\0'; - break; - } - } - int entry_size = atoi(buf); - if (entry_size == 0) { - r = -EINVAL; - std::cerr << "rbd: import data invalid format (zero entry size)" - << std::endl; - return false; - } - assert(entry_size > 0); - // Read entry. - r = bl.read_fd(m_fd, entry_size); - if (r < 0) { - std::cerr << "rbd: error reading from stdin: " << cpp_strerror(r) - << std::endl; - return false; - } - if (r != entry_size) { - std::cerr << "rbd: error reading from stdin: trucated" - << std::endl; - r = -EINVAL; - return false; - } - r = 0; - return true; - } - - int exec() { - int r = m_journaler.init(); - if (r < 0) { - return r; - } - m_journaler.start_append(0, 0, 0); - - int r1 = 0; - bufferlist bl; - int n = 0; - int error_count = 0; - while (read_entry(bl, r)) { - n++; - error_count++; - JSONParser p; - if (!p.parse(bl.c_str(), bl.length())) { - std::cerr << "rbd: error parsing input (entry " << n << ")" - << std::endl; - r = -EINVAL; - if (m_no_error) { - r1 = r; - continue; - } else { - break; - } - } - ExportEntry e; - try { - decode_json_obj(e, &p); - } catch (JSONDecoder::err& err) { - std::cerr << "rbd: error json decoding import data (entry " << n << "):" - << err.message << std::endl; - r = -EINVAL; - if (m_no_error) { - r1 = r; - continue; - } else { - break; - } - } - librbd::journal::EventEntry event_entry; - r = inspect_entry(e.entry, event_entry, m_verbose); - if (r < 0) { - std::cerr << "rbd: corrupted entry " << n << ": tag_tid=" << e.tag_id - << ", commit_tid=" << e.commit_tid << std::endl; - if (m_no_error) { - r1 = r; - continue; - } else { - break; - } - } - m_journaler.append(e.tag_id, e.entry); - error_count--; - } - - std::cout << n << " entries processed, " << error_count << " errors" << std::endl; - - std::cout << "Waiting for journal append to complete..." << std::endl; - - C_SaferCond cond; - m_journaler.stop_append(&cond); - r = cond.wait(); - - if (r < 0) { - std::cerr << "failed to append journal: " << cpp_strerror(r) << std::endl; - } - - if (r1 < 0 && r == 0) { - r = r1; - } - return r; - } - - int shut_down() { - return m_journaler.shut_down(); - } - -private: - Journaler m_journaler; - int m_fd; - bool m_no_error; - bool m_verbose; -}; - -static int do_import_journal(librados::IoCtx& io_ctx, - const std::string& journal_id, - const std::string& path, - bool no_error, bool verbose) { - int r; - - int fd; - bool from_stdin = path == "-"; - if (from_stdin) { - fd = STDIN_FILENO; - } else { - if ((fd = open(path.c_str(), O_RDONLY)) < 0) { - r = -errno; - std::cerr << "rbd: error opening " << path << std::endl; - return r; - } -#ifdef HAVE_POSIX_FADVISE - posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); -#endif - } - - JournalImporter importer(io_ctx, journal_id, fd, no_error, verbose); - r = importer.exec(); - - if (!from_stdin) { - close(fd); - } - - int shut_down_r = importer.shut_down(); - if (r == 0 && shut_down_r < 0) { - r = shut_down_r; - } - - return r; -} - -void get_info_arguments(po::options_description *positional, - po::options_description *options) { - at::add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE); - at::add_format_options(options); -} - -int execute_info(const po::variables_map &vm) { - size_t arg_index = 0; - std::string pool_name; - std::string journal_name; - int r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE, - &arg_index, &pool_name, &journal_name); - if (r < 0) { - return r; - } - - at::Format::Formatter formatter; - r = utils::get_formatter(vm, &formatter); - if (r < 0) { - return r; - } - - librados::Rados rados; - librados::IoCtx io_ctx; - r = utils::init(pool_name, &rados, &io_ctx); - if (r < 0) { - return r; - } - - r = do_show_journal_info(rados, io_ctx, journal_name, formatter.get()); - if (r < 0) { - std::cerr << "rbd: journal info: " << cpp_strerror(r) << std::endl; - return r; - } - return 0; - -} - -void get_status_arguments(po::options_description *positional, - po::options_description *options) { - at::add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE); - at::add_format_options(options); -} - -int execute_status(const po::variables_map &vm) { - size_t arg_index = 0; - std::string pool_name; - std::string journal_name; - int r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE, - &arg_index, &pool_name, &journal_name); - if (r < 0) { - return r; - } - - at::Format::Formatter formatter; - r = utils::get_formatter(vm, &formatter); - if (r < 0) { - return r; - } - - librados::Rados rados; - librados::IoCtx io_ctx; - r = utils::init(pool_name, &rados, &io_ctx); - if (r < 0) { - return r; - } - - r = do_show_journal_status(io_ctx, journal_name, formatter.get()); - if (r < 0) { - std::cerr << "rbd: journal status: " << cpp_strerror(r) << std::endl; - return r; - } - return 0; -} - -void get_reset_arguments(po::options_description *positional, - po::options_description *options) { - at::add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE); -} - -int execute_reset(const po::variables_map &vm) { - size_t arg_index = 0; - std::string pool_name; - std::string journal_name; - int r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE, - &arg_index, &pool_name, &journal_name); - if (r < 0) { - return r; - } - - librados::Rados rados; - librados::IoCtx io_ctx; - r = utils::init(pool_name, &rados, &io_ctx); - if (r < 0) { - return r; - } - - r = do_reset_journal(io_ctx, journal_name); - if (r < 0) { - std::cerr << "rbd: journal reset: " << cpp_strerror(r) << std::endl; - return r; - } - return 0; -} - -void get_client_disconnect_arguments(po::options_description *positional, - po::options_description *options) { - at::add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE); - options->add_options() - ("client-id", po::value(), - "client ID (or leave unspecified to disconnect all)"); -} - -int execute_client_disconnect(const po::variables_map &vm) { - size_t arg_index = 0; - std::string pool_name; - std::string journal_name; - int r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE, - &arg_index, &pool_name, &journal_name); - if (r < 0) { - return r; - } - - std::string client_id; - if (vm.count("client-id")) { - client_id = vm["client-id"].as(); - } - - librados::Rados rados; - librados::IoCtx io_ctx; - r = utils::init(pool_name, &rados, &io_ctx); - if (r < 0) { - return r; - } - - r = do_disconnect_journal_client(io_ctx, journal_name, client_id); - if (r < 0) { - std::cerr << "rbd: journal client disconnect: " << cpp_strerror(r) - << std::endl; - return r; - } - return 0; -} - -void get_inspect_arguments(po::options_description *positional, - po::options_description *options) { - at::add_journal_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE); - at::add_verbose_option(options); -} - -int execute_inspect(const po::variables_map &vm) { - size_t arg_index = 0; - std::string pool_name; - std::string journal_name; - int r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_NONE, - &arg_index, &pool_name, &journal_name); - if (r < 0) { - return r; - } - - librados::Rados rados; - librados::IoCtx io_ctx; - r = utils::init(pool_name, &rados, &io_ctx); - if (r < 0) { - return r; - } - - r = do_inspect_journal(io_ctx, journal_name, vm[at::VERBOSE].as()); - if (r < 0) { - std::cerr << "rbd: journal inspect: " << cpp_strerror(r) << std::endl; - return r; - } - return 0; -} - -void get_export_arguments(po::options_description *positional, - po::options_description *options) { - at::add_journal_spec_options(positional, options, - at::ARGUMENT_MODIFIER_SOURCE); - at::add_path_options(positional, options, - "export file (or '-' for stdout)"); - at::add_verbose_option(options); - at::add_no_error_option(options); -} - -int execute_export(const po::variables_map &vm) { - size_t arg_index = 0; - std::string pool_name; - std::string journal_name; - int r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_SOURCE, - &arg_index, &pool_name, &journal_name); - if (r < 0) { - return r; - } - - std::string path; - r = utils::get_path(vm, utils::get_positional_argument(vm, 1), &path); - if (r < 0) { - return r; - } - - librados::Rados rados; - librados::IoCtx io_ctx; - r = utils::init(pool_name, &rados, &io_ctx); - if (r < 0) { - return r; - } - - r = do_export_journal(io_ctx, journal_name, path, vm[at::NO_ERROR].as(), - vm[at::VERBOSE].as()); - if (r < 0) { - std::cerr << "rbd: journal export: " << cpp_strerror(r) << std::endl; - return r; - } - return 0; -} - -void get_import_arguments(po::options_description *positional, - 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); - at::add_verbose_option(options); - at::add_no_error_option(options); -} - -int execute_import(const po::variables_map &vm) { - std::string path; - int r = utils::get_path(vm, utils::get_positional_argument(vm, 0), &path); - if (r < 0) { - return r; - } - - size_t arg_index = 1; - std::string pool_name; - std::string journal_name; - r = utils::get_pool_journal_names(vm, at::ARGUMENT_MODIFIER_DEST, - &arg_index, &pool_name, &journal_name); - if (r < 0) { - return r; - } - - librados::Rados rados; - librados::IoCtx io_ctx; - r = utils::init(pool_name, &rados, &io_ctx); - if (r < 0) { - return r; - } - - r = do_import_journal(io_ctx, journal_name, path, vm[at::NO_ERROR].as(), - vm[at::VERBOSE].as()); - if (r < 0) { - std::cerr << "rbd: journal export: " << cpp_strerror(r) << std::endl; - return r; - } - return 0; -} - -Shell::Action action_info( - {"journal", "info"}, {}, "Show information about image journal.", "", - &get_info_arguments, &execute_info); - -Shell::Action action_status( - {"journal", "status"}, {}, "Show status of image journal.", "", - &get_status_arguments, &execute_status); - -Shell::Action action_reset( - {"journal", "reset"}, {}, "Reset image journal.", "", - &get_reset_arguments, &execute_reset); - -Shell::Action action_inspect( - {"journal", "inspect"}, {}, "Inspect image journal for structural errors.", "", - &get_inspect_arguments, &execute_inspect); - -Shell::Action action_export( - {"journal", "export"}, {}, "Export image journal.", "", - &get_export_arguments, &execute_export); - -Shell::Action action_import( - {"journal", "import"}, {}, "Import image journal.", "", - &get_import_arguments, &execute_import); - -Shell::Action action_disconnect( - {"journal", "client", "disconnect"}, {}, - "Flag image journal client as disconnected.", "", - &get_client_disconnect_arguments, &execute_client_disconnect); - -} // namespace journal -} // namespace action -} // namespace rbd