diff options
Diffstat (limited to 'src/librbd/migration/SourceSpecBuilder.cc')
-rw-r--r-- | src/librbd/migration/SourceSpecBuilder.cc | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/librbd/migration/SourceSpecBuilder.cc b/src/librbd/migration/SourceSpecBuilder.cc new file mode 100644 index 000000000..214d7ce0e --- /dev/null +++ b/src/librbd/migration/SourceSpecBuilder.cc @@ -0,0 +1,147 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "librbd/migration/SourceSpecBuilder.h" +#include "common/dout.h" +#include "librbd/ImageCtx.h" +#include "librbd/migration/FileStream.h" +#include "librbd/migration/HttpStream.h" +#include "librbd/migration/S3Stream.h" +#include "librbd/migration/NativeFormat.h" +#include "librbd/migration/QCOWFormat.h" +#include "librbd/migration/RawFormat.h" +#include "librbd/migration/RawSnapshot.h" + +#define dout_subsys ceph_subsys_rbd +#undef dout_prefix +#define dout_prefix *_dout << "librbd::migration::SourceSpecBuilder: " << this \ + << " " << __func__ << ": " + +namespace librbd { +namespace migration { + +namespace { + +const std::string STREAM_KEY{"stream"}; +const std::string TYPE_KEY{"type"}; + +} // anonymous namespace + +template <typename I> +int SourceSpecBuilder<I>::parse_source_spec( + const std::string& source_spec, + json_spirit::mObject* source_spec_object) const { + auto cct = m_image_ctx->cct; + ldout(cct, 10) << dendl; + + json_spirit::mValue json_root; + if(json_spirit::read(source_spec, json_root)) { + try { + *source_spec_object = json_root.get_obj(); + return 0; + } catch (std::runtime_error&) { + } + } + + lderr(cct) << "invalid source-spec JSON" << dendl; + return -EBADMSG; +} + +template <typename I> +int SourceSpecBuilder<I>::build_format( + const json_spirit::mObject& source_spec_object, bool import_only, + std::unique_ptr<FormatInterface>* format) const { + auto cct = m_image_ctx->cct; + ldout(cct, 10) << dendl; + + auto type_value_it = source_spec_object.find(TYPE_KEY); + if (type_value_it == source_spec_object.end() || + type_value_it->second.type() != json_spirit::str_type) { + lderr(cct) << "failed to locate format type value" << dendl; + return -EINVAL; + } + + auto& type = type_value_it->second.get_str(); + if (type == "native") { + format->reset(NativeFormat<I>::create(m_image_ctx, source_spec_object, + import_only)); + } else if (type == "qcow") { + format->reset(QCOWFormat<I>::create(m_image_ctx, source_spec_object, this)); + } else if (type == "raw") { + format->reset(RawFormat<I>::create(m_image_ctx, source_spec_object, this)); + } else { + lderr(cct) << "unknown or unsupported format type '" << type << "'" + << dendl; + return -ENOSYS; + } + return 0; +} + +template <typename I> +int SourceSpecBuilder<I>::build_snapshot( + const json_spirit::mObject& source_spec_object, uint64_t index, + std::shared_ptr<SnapshotInterface>* snapshot) const { + auto cct = m_image_ctx->cct; + ldout(cct, 10) << dendl; + + auto type_value_it = source_spec_object.find(TYPE_KEY); + if (type_value_it == source_spec_object.end() || + type_value_it->second.type() != json_spirit::str_type) { + lderr(cct) << "failed to locate snapshot type value" << dendl; + return -EINVAL; + } + + auto& type = type_value_it->second.get_str(); + if (type == "raw") { + snapshot->reset(RawSnapshot<I>::create(m_image_ctx, source_spec_object, + this, index)); + } else { + lderr(cct) << "unknown or unsupported format type '" << type << "'" + << dendl; + return -ENOSYS; + } + return 0; +} + +template <typename I> +int SourceSpecBuilder<I>::build_stream( + const json_spirit::mObject& source_spec_object, + std::shared_ptr<StreamInterface>* stream) const { + auto cct = m_image_ctx->cct; + ldout(cct, 10) << dendl; + + auto stream_value_it = source_spec_object.find(STREAM_KEY); + if (stream_value_it == source_spec_object.end() || + stream_value_it->second.type() != json_spirit::obj_type) { + lderr(cct) << "failed to locate stream object" << dendl; + return -EINVAL; + } + + auto& stream_obj = stream_value_it->second.get_obj(); + auto type_value_it = stream_obj.find(TYPE_KEY); + if (type_value_it == stream_obj.end() || + type_value_it->second.type() != json_spirit::str_type) { + lderr(cct) << "failed to locate stream type value" << dendl; + return -EINVAL; + } + + auto& type = type_value_it->second.get_str(); + if (type == "file") { + stream->reset(FileStream<I>::create(m_image_ctx, stream_obj)); + } else if (type == "http") { + stream->reset(HttpStream<I>::create(m_image_ctx, stream_obj)); + } else if (type == "s3") { + stream->reset(S3Stream<I>::create(m_image_ctx, stream_obj)); + } else { + lderr(cct) << "unknown or unsupported stream type '" << type << "'" + << dendl; + return -ENOSYS; + } + + return 0; +} + +} // namespace migration +} // namespace librbd + +template class librbd::migration::SourceSpecBuilder<librbd::ImageCtx>; |