summaryrefslogtreecommitdiffstats
path: root/src/librbd/migration/SourceSpecBuilder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/librbd/migration/SourceSpecBuilder.cc')
-rw-r--r--src/librbd/migration/SourceSpecBuilder.cc147
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>;