// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #include #include "cls/rbd/cls_rbd_types.h" #include "common/Formatter.h" namespace cls { namespace rbd { using std::istringstream; using std::ostringstream; using std::string; using ceph::bufferlist; using ceph::Formatter; std::ostream& operator<<(std::ostream& os, MirrorPeerDirection mirror_peer_direction) { switch (mirror_peer_direction) { case MIRROR_PEER_DIRECTION_RX: os << "RX"; break; case MIRROR_PEER_DIRECTION_TX: os << "TX"; break; case MIRROR_PEER_DIRECTION_RX_TX: os << "RX/TX"; break; default: os << "unknown"; break; } return os; } void MirrorPeer::encode(bufferlist &bl) const { ENCODE_START(2, 1, bl); encode(uuid, bl); encode(site_name, bl); encode(client_name, bl); int64_t pool_id = -1; encode(pool_id, bl); // v2 encode(static_cast(mirror_peer_direction), bl); encode(mirror_uuid, bl); encode(last_seen, bl); ENCODE_FINISH(bl); } void MirrorPeer::decode(bufferlist::const_iterator &it) { DECODE_START(2, it); decode(uuid, it); decode(site_name, it); decode(client_name, it); int64_t pool_id; decode(pool_id, it); if (struct_v >= 2) { uint8_t mpd; decode(mpd, it); mirror_peer_direction = static_cast(mpd); decode(mirror_uuid, it); decode(last_seen, it); } DECODE_FINISH(it); } void MirrorPeer::dump(Formatter *f) const { f->dump_string("uuid", uuid); f->dump_stream("direction") << mirror_peer_direction; f->dump_string("site_name", site_name); f->dump_string("mirror_uuid", mirror_uuid); f->dump_string("client_name", client_name); f->dump_stream("last_seen") << last_seen; } void MirrorPeer::generate_test_instances(std::list &o) { o.push_back(new MirrorPeer()); o.push_back(new MirrorPeer("uuid-123", MIRROR_PEER_DIRECTION_RX, "site A", "client name", "")); o.push_back(new MirrorPeer("uuid-234", MIRROR_PEER_DIRECTION_TX, "site B", "", "mirror_uuid")); o.push_back(new MirrorPeer("uuid-345", MIRROR_PEER_DIRECTION_RX_TX, "site C", "client name", "mirror_uuid")); } bool MirrorPeer::operator==(const MirrorPeer &rhs) const { return (uuid == rhs.uuid && mirror_peer_direction == rhs.mirror_peer_direction && site_name == rhs.site_name && client_name == rhs.client_name && mirror_uuid == rhs.mirror_uuid && last_seen == rhs.last_seen); } std::ostream& operator<<(std::ostream& os, const MirrorMode& mirror_mode) { switch (mirror_mode) { case MIRROR_MODE_DISABLED: os << "disabled"; break; case MIRROR_MODE_IMAGE: os << "image"; break; case MIRROR_MODE_POOL: os << "pool"; break; default: os << "unknown (" << static_cast(mirror_mode) << ")"; break; } return os; } std::ostream& operator<<(std::ostream& os, const MirrorPeer& peer) { os << "[" << "uuid=" << peer.uuid << ", " << "direction=" << peer.mirror_peer_direction << ", " << "site_name=" << peer.site_name << ", " << "client_name=" << peer.client_name << ", " << "mirror_uuid=" << peer.mirror_uuid << ", " << "last_seen=" << peer.last_seen << "]"; return os; } void MirrorImage::encode(bufferlist &bl) const { ENCODE_START(2, 1, bl); encode(global_image_id, bl); encode(static_cast(state), bl); encode(static_cast(mode), bl); ENCODE_FINISH(bl); } void MirrorImage::decode(bufferlist::const_iterator &it) { uint8_t int_state; DECODE_START(2, it); decode(global_image_id, it); decode(int_state, it); state = static_cast(int_state); if (struct_v >= 2) { uint8_t int_mode; decode(int_mode, it); mode = static_cast(int_mode); } DECODE_FINISH(it); } void MirrorImage::dump(Formatter *f) const { f->dump_stream("mode") << mode; f->dump_string("global_image_id", global_image_id); f->dump_stream("state") << state; } void MirrorImage::generate_test_instances(std::list &o) { o.push_back(new MirrorImage()); o.push_back(new MirrorImage(MIRROR_IMAGE_MODE_JOURNAL, "uuid-123", MIRROR_IMAGE_STATE_ENABLED)); o.push_back(new MirrorImage(MIRROR_IMAGE_MODE_SNAPSHOT, "uuid-abc", MIRROR_IMAGE_STATE_DISABLING)); } bool MirrorImage::operator==(const MirrorImage &rhs) const { return mode == rhs.mode && global_image_id == rhs.global_image_id && state == rhs.state; } bool MirrorImage::operator<(const MirrorImage &rhs) const { if (mode != rhs.mode) { return mode < rhs.mode; } if (global_image_id != rhs.global_image_id) { return global_image_id < rhs.global_image_id; } return state < rhs.state; } std::ostream& operator<<(std::ostream& os, const MirrorImageMode& mirror_mode) { switch (mirror_mode) { case MIRROR_IMAGE_MODE_JOURNAL: os << "journal"; break; case MIRROR_IMAGE_MODE_SNAPSHOT: os << "snapshot"; break; default: os << "unknown (" << static_cast(mirror_mode) << ")"; break; } return os; } std::ostream& operator<<(std::ostream& os, const MirrorImageState& mirror_state) { switch (mirror_state) { case MIRROR_IMAGE_STATE_DISABLING: os << "disabling"; break; case MIRROR_IMAGE_STATE_ENABLED: os << "enabled"; break; case MIRROR_IMAGE_STATE_DISABLED: os << "disabled"; break; default: os << "unknown (" << static_cast(mirror_state) << ")"; break; } return os; } std::ostream& operator<<(std::ostream& os, const MirrorImage& mirror_image) { os << "[" << "mode=" << mirror_image.mode << ", " << "global_image_id=" << mirror_image.global_image_id << ", " << "state=" << mirror_image.state << "]"; return os; } std::ostream& operator<<(std::ostream& os, const MirrorImageStatusState& state) { switch (state) { case MIRROR_IMAGE_STATUS_STATE_UNKNOWN: os << "unknown"; break; case MIRROR_IMAGE_STATUS_STATE_ERROR: os << "error"; break; case MIRROR_IMAGE_STATUS_STATE_SYNCING: os << "syncing"; break; case MIRROR_IMAGE_STATUS_STATE_STARTING_REPLAY: os << "starting_replay"; break; case MIRROR_IMAGE_STATUS_STATE_REPLAYING: os << "replaying"; break; case MIRROR_IMAGE_STATUS_STATE_STOPPING_REPLAY: os << "stopping_replay"; break; case MIRROR_IMAGE_STATUS_STATE_STOPPED: os << "stopped"; break; default: os << "unknown (" << static_cast(state) << ")"; break; } return os; } const std::string MirrorImageSiteStatus::LOCAL_MIRROR_UUID(""); // empty mirror uuid void MirrorImageSiteStatus::encode_meta(uint8_t version, bufferlist &bl) const { if (version >= 2) { ceph::encode(mirror_uuid, bl); } cls::rbd::encode(state, bl); ceph::encode(description, bl); ceph::encode(last_update, bl); ceph::encode(up, bl); } void MirrorImageSiteStatus::decode_meta(uint8_t version, bufferlist::const_iterator &it) { if (version < 2) { mirror_uuid = LOCAL_MIRROR_UUID; } else { ceph::decode(mirror_uuid, it); } cls::rbd::decode(state, it); ceph::decode(description, it); ::decode(last_update, it); ceph::decode(up, it); } void MirrorImageSiteStatus::encode(bufferlist &bl) const { // break compatibility when site-name is provided uint8_t version = (mirror_uuid == LOCAL_MIRROR_UUID ? 1 : 2); ENCODE_START(version, version, bl); encode_meta(version, bl); ENCODE_FINISH(bl); } void MirrorImageSiteStatus::decode(bufferlist::const_iterator &it) { DECODE_START(2, it); decode_meta(struct_v, it); DECODE_FINISH(it); } void MirrorImageSiteStatus::dump(Formatter *f) const { f->dump_string("state", state_to_string()); f->dump_string("description", description); f->dump_stream("last_update") << last_update; } std::string MirrorImageSiteStatus::state_to_string() const { std::stringstream ss; ss << (up ? "up+" : "down+") << state; return ss.str(); } void MirrorImageSiteStatus::generate_test_instances( std::list &o) { o.push_back(new MirrorImageSiteStatus()); o.push_back(new MirrorImageSiteStatus("", MIRROR_IMAGE_STATUS_STATE_REPLAYING, "")); o.push_back(new MirrorImageSiteStatus("", MIRROR_IMAGE_STATUS_STATE_ERROR, "error")); o.push_back(new MirrorImageSiteStatus("2fb68ca9-1ba0-43b3-8cdf-8c5a9db71e65", MIRROR_IMAGE_STATUS_STATE_STOPPED, "")); } bool MirrorImageSiteStatus::operator==(const MirrorImageSiteStatus &rhs) const { return state == rhs.state && description == rhs.description && up == rhs.up; } std::ostream& operator<<(std::ostream& os, const MirrorImageSiteStatus& status) { os << "{" << "state=" << status.state_to_string() << ", " << "description=" << status.description << ", " << "last_update=" << status.last_update << "]}"; return os; } void MirrorImageSiteStatusOnDisk::encode_meta(bufferlist &bl, uint64_t features) const { ENCODE_START(1, 1, bl); auto sanitized_origin = origin; sanitize_entity_inst(&sanitized_origin); encode(sanitized_origin, bl, features); ENCODE_FINISH(bl); } void MirrorImageSiteStatusOnDisk::encode(bufferlist &bl, uint64_t features) const { encode_meta(bl, features); cls::rbd::MirrorImageSiteStatus::encode(bl); } void MirrorImageSiteStatusOnDisk::decode_meta(bufferlist::const_iterator &it) { DECODE_START(1, it); decode(origin, it); sanitize_entity_inst(&origin); DECODE_FINISH(it); } void MirrorImageSiteStatusOnDisk::decode(bufferlist::const_iterator &it) { decode_meta(it); cls::rbd::MirrorImageSiteStatus::decode(it); } void MirrorImageSiteStatusOnDisk::generate_test_instances( std::list &o) { o.push_back(new MirrorImageSiteStatusOnDisk()); o.push_back(new MirrorImageSiteStatusOnDisk( {"", MIRROR_IMAGE_STATUS_STATE_ERROR, "error"})); o.push_back(new MirrorImageSiteStatusOnDisk( {"siteA", MIRROR_IMAGE_STATUS_STATE_STOPPED, ""})); } int MirrorImageStatus::get_local_mirror_image_site_status( MirrorImageSiteStatus* status) const { auto it = std::find_if( mirror_image_site_statuses.begin(), mirror_image_site_statuses.end(), [](const MirrorImageSiteStatus& status) { return status.mirror_uuid == MirrorImageSiteStatus::LOCAL_MIRROR_UUID; }); if (it == mirror_image_site_statuses.end()) { return -ENOENT; } *status = *it; return 0; } void MirrorImageStatus::encode(bufferlist &bl) const { // don't break compatibility for extra site statuses ENCODE_START(2, 1, bl); // local site status MirrorImageSiteStatus local_status; int r = get_local_mirror_image_site_status(&local_status); local_status.encode_meta(1, bl); bool local_status_valid = (r >= 0); encode(local_status_valid, bl); // remote site statuses __u32 n = mirror_image_site_statuses.size(); if (local_status_valid) { --n; } encode(n, bl); for (auto& status : mirror_image_site_statuses) { if (status.mirror_uuid == MirrorImageSiteStatus::LOCAL_MIRROR_UUID) { continue; } status.encode_meta(2, bl); } ENCODE_FINISH(bl); } void MirrorImageStatus::decode(bufferlist::const_iterator &it) { DECODE_START(2, it); // local site status MirrorImageSiteStatus local_status; local_status.decode_meta(1, it); if (struct_v < 2) { mirror_image_site_statuses.push_back(local_status); } else { bool local_status_valid; decode(local_status_valid, it); __u32 n; decode(n, it); if (local_status_valid) { ++n; } mirror_image_site_statuses.resize(n); for (auto status_it = mirror_image_site_statuses.begin(); status_it != mirror_image_site_statuses.end(); ++status_it) { if (local_status_valid && status_it == mirror_image_site_statuses.begin()) { *status_it = local_status; continue; } // remote site status status_it->decode_meta(struct_v, it); } } DECODE_FINISH(it); } void MirrorImageStatus::dump(Formatter *f) const { MirrorImageSiteStatus local_status; int r = get_local_mirror_image_site_status(&local_status); if (r >= 0) { local_status.dump(f); } f->open_array_section("remotes"); for (auto& status : mirror_image_site_statuses) { if (status.mirror_uuid == MirrorImageSiteStatus::LOCAL_MIRROR_UUID) { continue; } f->open_object_section("remote"); status.dump(f); f->close_section(); } f->close_section(); } bool MirrorImageStatus::operator==(const MirrorImageStatus &rhs) const { return (mirror_image_site_statuses == rhs.mirror_image_site_statuses); } void MirrorImageStatus::generate_test_instances( std::list &o) { o.push_back(new MirrorImageStatus()); o.push_back(new MirrorImageStatus({{"", MIRROR_IMAGE_STATUS_STATE_ERROR, ""}})); o.push_back(new MirrorImageStatus({{"", MIRROR_IMAGE_STATUS_STATE_STOPPED, ""}, {"siteA", MIRROR_IMAGE_STATUS_STATE_REPLAYING, ""}})); } std::ostream& operator<<(std::ostream& os, const MirrorImageStatus& status) { os << "{"; MirrorImageSiteStatus local_status; int r = status.get_local_mirror_image_site_status(&local_status); if (r >= 0) { os << "state=" << local_status.state_to_string() << ", " << "description=" << local_status.description << ", " << "last_update=" << local_status.last_update << ", "; } os << "remotes=["; for (auto& remote_status : status.mirror_image_site_statuses) { if (remote_status.mirror_uuid == MirrorImageSiteStatus::LOCAL_MIRROR_UUID) { continue; } os << "{" << "mirror_uuid=" << remote_status.mirror_uuid<< ", " << "state=" << remote_status.state_to_string() << ", " << "description=" << remote_status.description << ", " << "last_update=" << remote_status.last_update << "}"; } os << "]}"; return os; } void ParentImageSpec::encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); encode(pool_id, bl); encode(pool_namespace, bl); encode(image_id, bl); encode(snap_id, bl); ENCODE_FINISH(bl); } void ParentImageSpec::decode(bufferlist::const_iterator& bl) { DECODE_START(1, bl); decode(pool_id, bl); decode(pool_namespace, bl); decode(image_id, bl); decode(snap_id, bl); DECODE_FINISH(bl); } void ParentImageSpec::dump(Formatter *f) const { f->dump_int("pool_id", pool_id); f->dump_string("pool_namespace", pool_namespace); f->dump_string("image_id", image_id); f->dump_unsigned("snap_id", snap_id); } void ParentImageSpec::generate_test_instances(std::list& o) { o.push_back(new ParentImageSpec{}); o.push_back(new ParentImageSpec{1, "", "foo", 3}); o.push_back(new ParentImageSpec{1, "ns", "foo", 3}); } std::ostream& operator<<(std::ostream& os, const ParentImageSpec& rhs) { os << "[" << "pool_id=" << rhs.pool_id << ", " << "pool_namespace=" << rhs.pool_namespace << ", " << "image_id=" << rhs.image_id << ", " << "snap_id=" << rhs.snap_id << "]"; return os; } void ChildImageSpec::encode(bufferlist &bl) const { ENCODE_START(2, 1, bl); encode(pool_id, bl); encode(image_id, bl); encode(pool_namespace, bl); ENCODE_FINISH(bl); } void ChildImageSpec::decode(bufferlist::const_iterator &it) { DECODE_START(2, it); decode(pool_id, it); decode(image_id, it); if (struct_v >= 2) { decode(pool_namespace, it); } DECODE_FINISH(it); } void ChildImageSpec::dump(Formatter *f) const { f->dump_int("pool_id", pool_id); f->dump_string("pool_namespace", pool_namespace); f->dump_string("image_id", image_id); } void ChildImageSpec::generate_test_instances(std::list &o) { o.push_back(new ChildImageSpec()); o.push_back(new ChildImageSpec(123, "", "abc")); o.push_back(new ChildImageSpec(123, "ns", "abc")); } std::ostream& operator<<(std::ostream& os, const ChildImageSpec& rhs) { os << "[" << "pool_id=" << rhs.pool_id << ", " << "pool_namespace=" << rhs.pool_namespace << ", " << "image_id=" << rhs.image_id << "]"; return os; } void GroupImageSpec::encode(bufferlist &bl) const { ENCODE_START(1, 1, bl); encode(image_id, bl); encode(pool_id, bl); ENCODE_FINISH(bl); } void GroupImageSpec::decode(bufferlist::const_iterator &it) { DECODE_START(1, it); decode(image_id, it); decode(pool_id, it); DECODE_FINISH(it); } void GroupImageSpec::dump(Formatter *f) const { f->dump_string("image_id", image_id); f->dump_int("pool_id", pool_id); } int GroupImageSpec::from_key(const std::string &image_key, GroupImageSpec *spec) { if (nullptr == spec) return -EINVAL; int prefix_len = cls::rbd::RBD_GROUP_IMAGE_KEY_PREFIX.size(); std::string data_string = image_key.substr(prefix_len, image_key.size() - prefix_len); size_t p = data_string.find("_"); if (std::string::npos == p) { return -EIO; } data_string[p] = ' '; istringstream iss(data_string); uint64_t pool_id; string image_id; iss >> std::hex >> pool_id >> image_id; spec->image_id = image_id; spec->pool_id = pool_id; return 0; } std::string GroupImageSpec::image_key() { if (-1 == pool_id) return ""; else { ostringstream oss; oss << RBD_GROUP_IMAGE_KEY_PREFIX << std::setw(16) << std::setfill('0') << std::hex << pool_id << "_" << image_id; return oss.str(); } } void GroupImageSpec::generate_test_instances(std::list &o) { o.push_back(new GroupImageSpec("10152ae8944a", 0)); o.push_back(new GroupImageSpec("1018643c9869", 3)); } void GroupImageStatus::encode(bufferlist &bl) const { ENCODE_START(1, 1, bl); encode(spec, bl); encode(state, bl); ENCODE_FINISH(bl); } void GroupImageStatus::decode(bufferlist::const_iterator &it) { DECODE_START(1, it); decode(spec, it); decode(state, it); DECODE_FINISH(it); } std::string GroupImageStatus::state_to_string() const { std::stringstream ss; if (state == GROUP_IMAGE_LINK_STATE_INCOMPLETE) { ss << "incomplete"; } if (state == GROUP_IMAGE_LINK_STATE_ATTACHED) { ss << "attached"; } return ss.str(); } void GroupImageStatus::dump(Formatter *f) const { spec.dump(f); f->dump_string("state", state_to_string()); } void GroupImageStatus::generate_test_instances(std::list &o) { o.push_back(new GroupImageStatus(GroupImageSpec("10152ae8944a", 0), GROUP_IMAGE_LINK_STATE_ATTACHED)); o.push_back(new GroupImageStatus(GroupImageSpec("1018643c9869", 3), GROUP_IMAGE_LINK_STATE_ATTACHED)); o.push_back(new GroupImageStatus(GroupImageSpec("10152ae8944a", 0), GROUP_IMAGE_LINK_STATE_INCOMPLETE)); o.push_back(new GroupImageStatus(GroupImageSpec("1018643c9869", 3), GROUP_IMAGE_LINK_STATE_INCOMPLETE)); } void GroupSpec::encode(bufferlist &bl) const { ENCODE_START(1, 1, bl); encode(pool_id, bl); encode(group_id, bl); ENCODE_FINISH(bl); } void GroupSpec::decode(bufferlist::const_iterator &it) { DECODE_START(1, it); decode(pool_id, it); decode(group_id, it); DECODE_FINISH(it); } void GroupSpec::dump(Formatter *f) const { f->dump_string("group_id", group_id); f->dump_int("pool_id", pool_id); } bool GroupSpec::is_valid() const { return (!group_id.empty()) && (pool_id != -1); } void GroupSpec::generate_test_instances(std::list &o) { o.push_back(new GroupSpec("10152ae8944a", 0)); o.push_back(new GroupSpec("1018643c9869", 3)); } void GroupSnapshotNamespace::encode(bufferlist& bl) const { using ceph::encode; encode(group_pool, bl); encode(group_id, bl); encode(group_snapshot_id, bl); } void GroupSnapshotNamespace::decode(bufferlist::const_iterator& it) { using ceph::decode; decode(group_pool, it); decode(group_id, it); decode(group_snapshot_id, it); } void GroupSnapshotNamespace::dump(Formatter *f) const { f->dump_int("group_pool", group_pool); f->dump_string("group_id", group_id); f->dump_string("group_snapshot_id", group_snapshot_id); } void TrashSnapshotNamespace::encode(bufferlist& bl) const { using ceph::encode; encode(original_name, bl); encode(static_cast(original_snapshot_namespace_type), bl); } void TrashSnapshotNamespace::decode(bufferlist::const_iterator& it) { using ceph::decode; decode(original_name, it); uint32_t snap_type; decode(snap_type, it); original_snapshot_namespace_type = static_cast( snap_type); } void TrashSnapshotNamespace::dump(Formatter *f) const { f->dump_string("original_name", original_name); f->dump_stream("original_snapshot_namespace") << original_snapshot_namespace_type; } void MirrorSnapshotNamespace::encode(bufferlist& bl) const { using ceph::encode; encode(state, bl); encode(complete, bl); encode(mirror_peer_uuids, bl); encode(primary_mirror_uuid, bl); encode(primary_snap_id, bl); encode(last_copied_object_number, bl); encode(snap_seqs, bl); } void MirrorSnapshotNamespace::decode(bufferlist::const_iterator& it) { using ceph::decode; decode(state, it); decode(complete, it); decode(mirror_peer_uuids, it); decode(primary_mirror_uuid, it); decode(primary_snap_id, it); decode(last_copied_object_number, it); decode(snap_seqs, it); } void MirrorSnapshotNamespace::dump(Formatter *f) const { f->dump_stream("state") << state; f->dump_bool("complete", complete); f->open_array_section("mirror_peer_uuids"); for (auto &peer : mirror_peer_uuids) { f->dump_string("mirror_peer_uuid", peer); } f->close_section(); if (is_primary()) { f->dump_unsigned("clean_since_snap_id", clean_since_snap_id); } else { f->dump_string("primary_mirror_uuid", primary_mirror_uuid); f->dump_unsigned("primary_snap_id", primary_snap_id); f->dump_unsigned("last_copied_object_number", last_copied_object_number); f->dump_stream("snap_seqs") << snap_seqs; } } class EncodeSnapshotNamespaceVisitor { public: explicit EncodeSnapshotNamespaceVisitor(bufferlist &bl) : m_bl(bl) { } template inline void operator()(const T& t) const { using ceph::encode; encode(static_cast(T::SNAPSHOT_NAMESPACE_TYPE), m_bl); t.encode(m_bl); } private: bufferlist &m_bl; }; class DecodeSnapshotNamespaceVisitor { public: DecodeSnapshotNamespaceVisitor(bufferlist::const_iterator &iter) : m_iter(iter) { } template inline void operator()(T& t) const { t.decode(m_iter); } private: bufferlist::const_iterator &m_iter; }; class DumpSnapshotNamespaceVisitor { public: explicit DumpSnapshotNamespaceVisitor(Formatter *formatter, const std::string &key) : m_formatter(formatter), m_key(key) {} template inline void operator()(const T& t) const { auto type = T::SNAPSHOT_NAMESPACE_TYPE; m_formatter->dump_string(m_key.c_str(), stringify(type)); t.dump(m_formatter); } private: ceph::Formatter *m_formatter; std::string m_key; }; class GetTypeVisitor { public: template inline SnapshotNamespaceType operator()(const T&) const { return static_cast(T::SNAPSHOT_NAMESPACE_TYPE); } }; SnapshotNamespaceType get_snap_namespace_type( const SnapshotNamespace& snapshot_namespace) { return static_cast(snapshot_namespace.visit( GetTypeVisitor())); } void SnapshotInfo::encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); encode(id, bl); encode(snapshot_namespace, bl); encode(name, bl); encode(image_size, bl); encode(timestamp, bl); encode(child_count, bl); ENCODE_FINISH(bl); } void SnapshotInfo::decode(bufferlist::const_iterator& it) { DECODE_START(1, it); decode(id, it); decode(snapshot_namespace, it); decode(name, it); decode(image_size, it); decode(timestamp, it); decode(child_count, it); DECODE_FINISH(it); } void SnapshotInfo::dump(Formatter *f) const { f->dump_unsigned("id", id); f->open_object_section("namespace"); snapshot_namespace.visit(DumpSnapshotNamespaceVisitor(f, "type")); f->close_section(); f->dump_string("name", name); f->dump_unsigned("image_size", image_size); f->dump_stream("timestamp") << timestamp; } void SnapshotInfo::generate_test_instances(std::list &o) { o.push_back(new SnapshotInfo(1ULL, UserSnapshotNamespace{}, "snap1", 123, {123456, 0}, 12)); o.push_back(new SnapshotInfo(2ULL, GroupSnapshotNamespace{567, "group1", "snap1"}, "snap1", 123, {123456, 0}, 987)); o.push_back(new SnapshotInfo(3ULL, TrashSnapshotNamespace{ SNAPSHOT_NAMESPACE_TYPE_USER, "snap1"}, "12345", 123, {123456, 0}, 429)); o.push_back(new SnapshotInfo(1ULL, MirrorSnapshotNamespace{MIRROR_SNAPSHOT_STATE_PRIMARY, {"1", "2"}, "", CEPH_NOSNAP}, "snap1", 123, {123456, 0}, 12)); o.push_back(new SnapshotInfo(1ULL, MirrorSnapshotNamespace{MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {"1", "2"}, "uuid", 123}, "snap1", 123, {123456, 0}, 12)); } void SnapshotNamespace::encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); visit(EncodeSnapshotNamespaceVisitor(bl)); ENCODE_FINISH(bl); } void SnapshotNamespace::decode(bufferlist::const_iterator &p) { DECODE_START(1, p); uint32_t snap_type; decode(snap_type, p); switch (snap_type) { case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_USER: *this = UserSnapshotNamespace(); break; case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_GROUP: *this = GroupSnapshotNamespace(); break; case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_TRASH: *this = TrashSnapshotNamespace(); break; case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR: *this = MirrorSnapshotNamespace(); break; default: *this = UnknownSnapshotNamespace(); break; } visit(DecodeSnapshotNamespaceVisitor(p)); DECODE_FINISH(p); } void SnapshotNamespace::dump(Formatter *f) const { visit(DumpSnapshotNamespaceVisitor(f, "snapshot_namespace_type")); } void SnapshotNamespace::generate_test_instances(std::list &o) { o.push_back(new SnapshotNamespace(UserSnapshotNamespace())); o.push_back(new SnapshotNamespace(GroupSnapshotNamespace(0, "10152ae8944a", "2118643c9732"))); o.push_back(new SnapshotNamespace(GroupSnapshotNamespace(5, "1018643c9869", "33352be8933c"))); o.push_back(new SnapshotNamespace(TrashSnapshotNamespace())); o.push_back(new SnapshotNamespace(MirrorSnapshotNamespace(MIRROR_SNAPSHOT_STATE_PRIMARY, {"peer uuid"}, "", CEPH_NOSNAP))); o.push_back(new SnapshotNamespace(MirrorSnapshotNamespace(MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED, {"peer uuid"}, "", CEPH_NOSNAP))); o.push_back(new SnapshotNamespace(MirrorSnapshotNamespace(MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {"peer uuid"}, "uuid", 123))); o.push_back(new SnapshotNamespace(MirrorSnapshotNamespace(MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED, {"peer uuid"}, "uuid", 123))); } std::ostream& operator<<(std::ostream& os, const SnapshotNamespace& ns) { return ns.visit([&os](const auto& val) -> std::ostream& { return os << val; }); } std::ostream& operator<<(std::ostream& os, const SnapshotNamespaceType& type) { switch (type) { case SNAPSHOT_NAMESPACE_TYPE_USER: os << "user"; break; case SNAPSHOT_NAMESPACE_TYPE_GROUP: os << "group"; break; case SNAPSHOT_NAMESPACE_TYPE_TRASH: os << "trash"; break; case SNAPSHOT_NAMESPACE_TYPE_MIRROR: os << "mirror"; break; default: os << "unknown"; break; } return os; } std::ostream& operator<<(std::ostream& os, const UserSnapshotNamespace& ns) { os << "[" << SNAPSHOT_NAMESPACE_TYPE_USER << "]"; return os; } std::ostream& operator<<(std::ostream& os, const GroupSnapshotNamespace& ns) { os << "[" << SNAPSHOT_NAMESPACE_TYPE_GROUP << " " << "group_pool=" << ns.group_pool << ", " << "group_id=" << ns.group_id << ", " << "group_snapshot_id=" << ns.group_snapshot_id << "]"; return os; } std::ostream& operator<<(std::ostream& os, const TrashSnapshotNamespace& ns) { os << "[" << SNAPSHOT_NAMESPACE_TYPE_TRASH << " " << "original_name=" << ns.original_name << ", " << "original_snapshot_namespace=" << ns.original_snapshot_namespace_type << "]"; return os; } std::ostream& operator<<(std::ostream& os, const MirrorSnapshotNamespace& ns) { os << "[" << SNAPSHOT_NAMESPACE_TYPE_MIRROR << " " << "state=" << ns.state << ", " << "complete=" << ns.complete << ", " << "mirror_peer_uuids=" << ns.mirror_peer_uuids << ", "; if (ns.is_primary()) { os << "clean_since_snap_id=" << ns.clean_since_snap_id; } else { os << "primary_mirror_uuid=" << ns.primary_mirror_uuid << ", " << "primary_snap_id=" << ns.primary_snap_id << ", " << "last_copied_object_number=" << ns.last_copied_object_number << ", " << "snap_seqs=" << ns.snap_seqs; } os << "]"; return os; } std::ostream& operator<<(std::ostream& os, const UnknownSnapshotNamespace& ns) { os << "[unknown]"; return os; } std::ostream& operator<<(std::ostream& os, MirrorSnapshotState type) { switch (type) { case MIRROR_SNAPSHOT_STATE_PRIMARY: os << "primary"; break; case MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED: os << "primary (demoted)"; break; case MIRROR_SNAPSHOT_STATE_NON_PRIMARY: os << "non-primary"; break; case MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED: os << "non-primary (demoted)"; break; default: os << "unknown"; break; } return os; } void ImageSnapshotSpec::encode(bufferlist& bl) const { using ceph::encode; ENCODE_START(1, 1, bl); encode(pool, bl); encode(image_id, bl); encode(snap_id, bl); ENCODE_FINISH(bl); } void ImageSnapshotSpec::decode(bufferlist::const_iterator& it) { using ceph::decode; DECODE_START(1, it); decode(pool, it); decode(image_id, it); decode(snap_id, it); DECODE_FINISH(it); } void ImageSnapshotSpec::dump(Formatter *f) const { f->dump_int("pool", pool); f->dump_string("image_id", image_id); f->dump_int("snap_id", snap_id); } void ImageSnapshotSpec::generate_test_instances(std::list &o) { o.push_back(new ImageSnapshotSpec(0, "myimage", 2)); o.push_back(new ImageSnapshotSpec(1, "testimage", 7)); } void GroupSnapshot::encode(bufferlist& bl) const { using ceph::encode; ENCODE_START(1, 1, bl); encode(id, bl); encode(name, bl); encode(state, bl); encode(snaps, bl); ENCODE_FINISH(bl); } void GroupSnapshot::decode(bufferlist::const_iterator& it) { using ceph::decode; DECODE_START(1, it); decode(id, it); decode(name, it); decode(state, it); decode(snaps, it); DECODE_FINISH(it); } void GroupSnapshot::dump(Formatter *f) const { f->dump_string("id", id); f->dump_string("name", name); f->dump_int("state", state); } void GroupSnapshot::generate_test_instances(std::list &o) { o.push_back(new GroupSnapshot("10152ae8944a", "groupsnapshot1", GROUP_SNAPSHOT_STATE_INCOMPLETE)); o.push_back(new GroupSnapshot("1018643c9869", "groupsnapshot2", GROUP_SNAPSHOT_STATE_COMPLETE)); } void TrashImageSpec::encode(bufferlist& bl) const { ENCODE_START(2, 1, bl); encode(source, bl); encode(name, bl); encode(deletion_time, bl); encode(deferment_end_time, bl); encode(state, bl); ENCODE_FINISH(bl); } void TrashImageSpec::decode(bufferlist::const_iterator &it) { DECODE_START(2, it); decode(source, it); decode(name, it); decode(deletion_time, it); decode(deferment_end_time, it); if (struct_v >= 2) { decode(state, it); } DECODE_FINISH(it); } void TrashImageSpec::dump(Formatter *f) const { f->dump_stream("source") << source; f->dump_string("name", name); f->dump_unsigned("deletion_time", deletion_time); f->dump_unsigned("deferment_end_time", deferment_end_time); } void MirrorImageMap::encode(bufferlist &bl) const { ENCODE_START(1, 1, bl); encode(instance_id, bl); encode(mapped_time, bl); encode(data, bl); ENCODE_FINISH(bl); } void MirrorImageMap::decode(bufferlist::const_iterator &it) { DECODE_START(1, it); decode(instance_id, it); decode(mapped_time, it); decode(data, it); DECODE_FINISH(it); } void MirrorImageMap::dump(Formatter *f) const { f->dump_string("instance_id", instance_id); f->dump_stream("mapped_time") << mapped_time; std::stringstream data_ss; data.hexdump(data_ss); f->dump_string("data", data_ss.str()); } void MirrorImageMap::generate_test_instances( std::list &o) { bufferlist data; data.append(std::string(128, '1')); o.push_back(new MirrorImageMap("uuid-123", utime_t(), data)); o.push_back(new MirrorImageMap("uuid-abc", utime_t(), data)); } bool MirrorImageMap::operator==(const MirrorImageMap &rhs) const { return instance_id == rhs.instance_id && mapped_time == rhs.mapped_time && data.contents_equal(rhs.data); } bool MirrorImageMap::operator<(const MirrorImageMap &rhs) const { return instance_id < rhs.instance_id || (instance_id == rhs.instance_id && mapped_time < rhs.mapped_time); } std::ostream& operator<<(std::ostream& os, const MirrorImageMap &image_map) { return os << "[" << "instance_id=" << image_map.instance_id << ", mapped_time=" << image_map.mapped_time << "]"; } std::ostream& operator<<(std::ostream& os, const MigrationHeaderType& type) { switch (type) { case MIGRATION_HEADER_TYPE_SRC: os << "source"; break; case MIGRATION_HEADER_TYPE_DST: os << "destination"; break; default: os << "unknown (" << static_cast(type) << ")"; break; } return os; } std::ostream& operator<<(std::ostream& os, const MigrationState& migration_state) { switch (migration_state) { case MIGRATION_STATE_ERROR: os << "error"; break; case MIGRATION_STATE_PREPARING: os << "preparing"; break; case MIGRATION_STATE_PREPARED: os << "prepared"; break; case MIGRATION_STATE_EXECUTING: os << "executing"; break; case MIGRATION_STATE_EXECUTED: os << "executed"; break; case MIGRATION_STATE_ABORTING: os << "aborting"; break; default: os << "unknown (" << static_cast(migration_state) << ")"; break; } return os; } void MigrationSpec::encode(bufferlist& bl) const { uint8_t min_version = 1; if (!source_spec.empty()) { min_version = 3; } ENCODE_START(3, min_version, bl); encode(header_type, bl); encode(pool_id, bl); encode(pool_namespace, bl); encode(image_name, bl); encode(image_id, bl); encode(snap_seqs, bl); encode(overlap, bl); encode(flatten, bl); encode(mirroring, bl); encode(state, bl); encode(state_description, bl); encode(static_cast(mirror_image_mode), bl); encode(source_spec, bl); ENCODE_FINISH(bl); } void MigrationSpec::decode(bufferlist::const_iterator& bl) { DECODE_START(3, bl); decode(header_type, bl); decode(pool_id, bl); decode(pool_namespace, bl); decode(image_name, bl); decode(image_id, bl); decode(snap_seqs, bl); decode(overlap, bl); decode(flatten, bl); decode(mirroring, bl); decode(state, bl); decode(state_description, bl); if (struct_v >= 2) { uint8_t int_mode; decode(int_mode, bl); mirror_image_mode = static_cast(int_mode); } if (struct_v >= 3) { decode(source_spec, bl); } DECODE_FINISH(bl); } std::ostream& operator<<(std::ostream& os, const std::map& snap_seqs) { os << "{"; size_t count = 0; for (auto &it : snap_seqs) { os << (count++ > 0 ? ", " : "") << "(" << it.first << ", " << it.second << ")"; } os << "}"; return os; } void MigrationSpec::dump(Formatter *f) const { f->dump_stream("header_type") << header_type; if (header_type == MIGRATION_HEADER_TYPE_SRC || source_spec.empty()) { f->dump_int("pool_id", pool_id); f->dump_string("pool_namespace", pool_namespace); f->dump_string("image_name", image_name); f->dump_string("image_id", image_id); } else { f->dump_string("source_spec", source_spec); } f->dump_stream("snap_seqs") << snap_seqs; f->dump_unsigned("overlap", overlap); f->dump_bool("mirroring", mirroring); f->dump_stream("mirror_image_mode") << mirror_image_mode; } void MigrationSpec::generate_test_instances(std::list &o) { o.push_back(new MigrationSpec()); o.push_back(new MigrationSpec(MIGRATION_HEADER_TYPE_SRC, 1, "ns", "image_name", "image_id", "", {{1, 2}}, 123, true, MIRROR_IMAGE_MODE_SNAPSHOT, true, MIGRATION_STATE_PREPARED, "description")); o.push_back(new MigrationSpec(MIGRATION_HEADER_TYPE_DST, -1, "", "", "", "{\"format\": \"raw\"}", {{1, 2}}, 123, true, MIRROR_IMAGE_MODE_SNAPSHOT, true, MIGRATION_STATE_PREPARED, "description")); } std::ostream& operator<<(std::ostream& os, const MigrationSpec& migration_spec) { os << "[" << "header_type=" << migration_spec.header_type << ", "; if (migration_spec.header_type == MIGRATION_HEADER_TYPE_SRC || migration_spec.source_spec.empty()) { os << "pool_id=" << migration_spec.pool_id << ", " << "pool_namespace=" << migration_spec.pool_namespace << ", " << "image_name=" << migration_spec.image_name << ", " << "image_id=" << migration_spec.image_id << ", "; } else { os << "source_spec=" << migration_spec.source_spec << ", "; } os << "snap_seqs=" << migration_spec.snap_seqs << ", " << "overlap=" << migration_spec.overlap << ", " << "flatten=" << migration_spec.flatten << ", " << "mirroring=" << migration_spec.mirroring << ", " << "mirror_image_mode=" << migration_spec.mirror_image_mode << ", " << "state=" << migration_spec.state << ", " << "state_description=" << migration_spec.state_description << "]"; return os; } std::ostream& operator<<(std::ostream& os, const AssertSnapcSeqState& state) { switch (state) { case ASSERT_SNAPC_SEQ_GT_SNAPSET_SEQ: os << "gt"; break; case ASSERT_SNAPC_SEQ_LE_SNAPSET_SEQ: os << "le"; break; default: os << "unknown (" << static_cast(state) << ")"; break; } return os; } void sanitize_entity_inst(entity_inst_t* entity_inst) { // make all addrs of type ANY because the type isn't what uniquely // identifies them and clients and on-disk formats can be encoded // with different backwards compatibility settings. entity_inst->addr.set_type(entity_addr_t::TYPE_ANY); } } // namespace rbd } // namespace cls