| 64 | } |
| 65 | |
| 66 | auto AdminSocket::parse_cmd(const std::vector<std::string>& cmd) |
| 67 | -> std::variant<parsed_command_t, tell_result_t> |
| 68 | { |
| 69 | LOG_PREFIX(AdminSocket::parse_cmd); |
| 70 | INFO(""); |
| 71 | // preliminaries: |
| 72 | // - create the formatter specified by the cmd parameters |
| 73 | // - locate the "op-code" string (the 'prefix' segment) |
| 74 | // - prepare for command parameters extraction via cmdmap_t |
| 75 | cmdmap_t cmdmap; |
| 76 | ceph::bufferlist out; |
| 77 | |
| 78 | try { |
| 79 | stringstream errss; |
| 80 | // note that cmdmap_from_json() may throw on syntax issues |
| 81 | if (!cmdmap_from_json(cmd, &cmdmap, errss)) { |
| 82 | ERROR("incoming command error: {}", errss.str()); |
| 83 | out.append("error:"s); |
| 84 | out.append(errss.str()); |
| 85 | return tell_result_t{-EINVAL, "invalid json", std::move(out)}; |
| 86 | } |
| 87 | } catch (const std::runtime_error& e) { |
| 88 | ERROR("incoming command syntax: {}", cmd); |
| 89 | out.append(string{e.what()}); |
| 90 | return tell_result_t{-EINVAL, "invalid json", std::move(out)}; |
| 91 | } |
| 92 | |
| 93 | string format; |
| 94 | string prefix; |
| 95 | try { |
| 96 | cmd_getval(cmdmap, "format", format); |
| 97 | cmd_getval(cmdmap, "prefix", prefix); |
| 98 | // tolerate old-style pg <pgid> command <args> style formatting |
| 99 | if (prefix == "pg") { |
| 100 | std::string pg_subcmd; |
| 101 | cmd_getval(cmdmap, "cmd", pg_subcmd); |
| 102 | prefix = pg_subcmd; |
| 103 | |
| 104 | if (auto arg = cmd_getval<std::string>(cmdmap, "arg"); arg) { |
| 105 | if (pg_subcmd == "list_unfound") { |
| 106 | cmdmap["offset"] = std::move(*arg); |
| 107 | } else if (pg_subcmd == "mark_unfound_lost") { |
| 108 | cmdmap["mulcmd"] = std::move(*arg); |
| 109 | } |
| 110 | cmdmap.erase("arg"); |
| 111 | } |
| 112 | } |
| 113 | } catch (const bad_cmd_get& e) { |
| 114 | ERROR("invalid syntax: {}", cmd); |
| 115 | out.append(string{e.what()}); |
| 116 | return tell_result_t{-EINVAL, "invalid json", std::move(out)}; |
| 117 | } |
| 118 | |
| 119 | // match the incoming op-code to one of the registered APIs |
| 120 | auto found = hooks.find(prefix); |
| 121 | if (found == hooks.end()) { |
| 122 | ERROR("unknown command: {}", prefix); |
| 123 | return tell_result_t{-EINVAL, |
nothing calls this directly
no test coverage detected