]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
objectstore_tool: lookup objects by name
authorLoic Dachary <ldachary@redhat.com>
Wed, 26 Nov 2014 22:34:22 +0000 (23:34 +0100)
committerDavid Zafman <dzafman@redhat.com>
Tue, 3 Mar 2015 19:20:58 +0000 (11:20 -0800)
If the object is not a parsable JSON string, assume an object name and
look it up in all the PGs. If multiple objects have the same name, only
apply the command to one of them. It is primarily useful in a test
environment where the names of the tests objects are known and only a
small number of objects exists. It replaces the following:

    path='--data-path dev/osd0 --journal-path dev/osd0.journal'
    for pgid in $(./ceph_objectstore_tool $path --op list-pgs) ; do
      object=$(./ceph_objectstore_tool $path --pgid $pgid --op list |
               grep '"oid":"NAME"')
      test -n "$object" && break
    done
    ./ceph_objectstore_tool $path --pgid $pgid "$object" remove

with:

    ./ceph_objectstore_tool $path NAME remove

http://tracker.ceph.com/issues/10192 Fixes: #10192

Signed-off-by: Loic Dachary <ldachary@redhat.com>
(cherry picked from commit 7c1165f96391821c00cca1ac04b3433dbec6bb6e)

Conflicts:
src/tools/ceph_objectstore_tool.cc

src/tools/ceph_objectstore_tool.cc

index 55d808b1c6798c9d54ac3d32330b423b665c7703..ff1fc3b32dfc86d67e3334d35523b516f0150d9b 100644 (file)
@@ -448,6 +448,57 @@ int action_on_all_objects(ObjectStore *store, action_on_object_t &action, bool d
   store->sync_and_flush();
   return r;
 }
+
+struct pgid_object_list {
+  list<pair<coll_t, ghobject_t> > _objects;
+
+  void insert(coll_t coll, ghobject_t &ghobj) {
+    _objects.push_back(make_pair(coll, ghobj));
+  }
+
+  void dump(Formatter *f) const {
+    f->open_array_section("pgid_objects");
+    for (list<pair<coll_t, ghobject_t> >::const_iterator i = _objects.begin();
+        i != _objects.end();
+        i++) {
+      f->open_array_section("pgid_object");
+      i->first.dump(f);
+      f->open_object_section("ghobject");
+      i->second.dump(f);
+      f->close_section();
+      f->close_section();
+    }
+    f->close_section();
+  }
+};
+
+struct lookup_ghobject : public action_on_object_t {
+  pgid_object_list _objects;
+  const string _name;
+
+  lookup_ghobject(const string& name) : _name(name) { }
+
+  virtual int call(ObjectStore *store, coll_t coll, ghobject_t &ghobj, object_info_t &oi) {
+    if (_name.length() == 0 || ghobj.hobj.oid.name == _name)
+      _objects.insert(coll, ghobj);
+    return 0;
+  }
+
+  int size() const {
+    return _objects._objects.size();
+  }
+
+  pair<coll_t, ghobject_t> pop() {
+     pair<coll_t, ghobject_t> front = _objects._objects.front();
+     _objects._objects.pop_front();
+     return front;
+  }
+
+  void dump(Formatter *f) const {
+    _objects.dump(f);
+  }
+};
+
 hobject_t infos_oid = OSD::make_infos_oid();
 hobject_t biginfo_oid, log_oid;
 
@@ -1940,8 +1991,6 @@ void usage(po::options_description &desc)
     cerr << std::endl;
     cerr << "Positional syntax:" << std::endl;
     cerr << std::endl;
-    cerr << "(requires --data-path, --journal-path (for filestore type) and --pgid to be specified)" << std::endl;
-    cerr << "(optional [file] argument will read stdin or write stdout if not specified or if '-' specified)" << std::endl;
     cerr << "ceph-objectstore-tool ... <object> (get|set)-bytes [file]" << std::endl;
     cerr << "ceph-objectstore-tool ... <object> set-(attr|omap) <key> [file]" << std::endl;
     cerr << "ceph-objectstore-tool ... <object> (get|rm)-(attr|omap) <key>" << std::endl;
@@ -1953,12 +2002,20 @@ void usage(po::options_description &desc)
     cerr << std::endl;
     cerr << "ceph-objectstore-tool import-rados <pool> [file]" << std::endl;
     cerr << std::endl;
+    cerr << "<object> can be a JSON object description as displayed" << std::endl;
+    cerr << "by --op list, with a mandatory --pgid option." << std::endl;
+    cerr << "<object> can be an object name which will be looked up in all" << std::endl;
+    cerr << "the OSD's PGs." << std::endl;
+    cerr << std::endl;
+    cerr << "The optional [file] argument will read stdin or write stdout" << std::endl;
+    cerr << "if not specified or if '-' specified." << std::endl;
     exit(1);
 }
 
 int main(int argc, char **argv)
 {
   string dpath, jpath, pgidstr, op, file, object, objcmd, arg1, arg2, type;
+  spg_t pgid;
   ghobject_t ghobj;
 
   po::options_description desc("Allowed options");
@@ -2075,24 +2132,6 @@ int main(int argc, char **argv)
     cerr << "Can't specify both --op and object command syntax" << std::endl;
     usage(desc);
   }
-  if (op != "import" && op != "list-lost" && op != "fix-lost"
-      && op != "list-pgs"  && op != "set-allow-sharded-objects" && !vm.count("pgid")) {
-    cerr << "Must provide pgid" << std::endl;
-    usage(desc);
-  }
-
-  if (vm.count("object")) {
-    json_spirit::Value v;
-    try {
-      if (!json_spirit::read(object, v))
-        throw std::runtime_error("bad json");
-      ghobj.decode(v);
-    } catch (std::runtime_error& e) {
-      cerr << "error parsing offset: " << e.what() << std::endl;
-      exit(1);
-    }
-  }
-
   outistty = isatty(STDOUT_FILENO);
 
   file_fd = fd_none;
@@ -2133,11 +2172,6 @@ int main(int argc, char **argv)
     return 1;
   }
 
-  if (op == "import" && pgidstr.length()) {
-    cerr << "--pgid option invalid with import" << std::endl;
-    return 1;
-  }
-
   vector<const char *> ceph_options;
   env_to_vec(ceph_options);
   vector<string> ceph_option_strings = po::collect_unrecognized(
@@ -2196,12 +2230,6 @@ int main(int argc, char **argv)
     }
   }
 
-  spg_t pgid;
-  if (pgidstr.length() && !pgid.parse(pgidstr.c_str())) {
-    cerr << "Invalid pgid '" << pgidstr << "' specified" << std::endl;
-    return 1;
-  }
-
   ObjectStore *fs = ObjectStore::create(g_ceph_context, type, dpath, jpath, flags);
   if (fs == NULL) {
     cerr << "Must provide --type (filestore, memstore, keyvaluestore-dev)" << std::endl;
@@ -2261,6 +2289,52 @@ int main(int argc, char **argv)
     goto out;
   }
 
+  if (pgidstr.length() && !pgid.parse(pgidstr.c_str())) {
+    cerr << "Invalid pgid '" << pgidstr << "' specified" << std::endl;
+    return 1;
+  }
+
+  if (op == "import" && pgidstr.length()) {
+    cerr << "--pgid option invalid with import" << std::endl;
+    return 1;
+  }
+
+  if (vm.count("object")) {
+    json_spirit::Value v;
+    try {
+      if (!json_spirit::read(object, v)) {
+       lookup_ghobject lookup(object);
+       if (action_on_all_objects(fs, lookup, debug)) {
+         throw std::runtime_error(object + " is neither valid json nor an object name");
+       } else {
+         if (lookup.size() != 1) {
+           stringstream ss;
+           ss << "expected a single object named " << object
+              << " but got " << lookup.size() << " instead"
+              << std::endl;
+           throw std::runtime_error(ss.str());
+         }
+         pair<coll_t, ghobject_t> found = lookup.pop();
+         pgidstr = found.first.to_str();
+         pgid.parse(pgidstr.c_str());
+         ghobj = found.second;
+       }
+      } else {
+       ghobj.decode(v);
+      }
+    } catch (std::runtime_error& e) {
+      cerr << e.what() << std::endl;
+      exit(1);
+    }
+  }
+
+  if (op != "import" && op != "list-lost" && op != "fix-lost"
+      && op != "list-pgs"  && op != "set-allow-sharded-objects" &&
+      (pgidstr.length() == 0)) {
+    cerr << "Must provide pgid" << std::endl;
+    usage(desc);
+  }
+
   if (op == "set-allow-sharded-objects") {
     // This could only happen if we backport changes to an older release
     if (!supported.incompat.contains(CEPH_OSD_FEATURE_INCOMPAT_SHARDS)) {