]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_admin.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / rgw / rgw_admin.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include <errno.h>
5 #include <iostream>
6 #include <sstream>
7 #include <string>
8
9 #include <boost/optional.hpp>
10
11 #include "auth/Crypto.h"
12
13 #include "common/armor.h"
14 #include "common/ceph_json.h"
15 #include "common/config.h"
16 #include "common/ceph_argparse.h"
17 #include "common/Formatter.h"
18 #include "common/errno.h"
19 #include "common/safe_io.h"
20
21 #include "cls/rgw/cls_rgw_client.h"
22
23 #include "global/global_init.h"
24
25 #include "include/utime.h"
26 #include "include/str_list.h"
27
28 #include "rgw_user.h"
29 #include "rgw_bucket.h"
30 #include "rgw_rados.h"
31 #include "rgw_acl.h"
32 #include "rgw_acl_s3.h"
33 #include "rgw_lc.h"
34 #include "rgw_log.h"
35 #include "rgw_formats.h"
36 #include "rgw_usage.h"
37 #include "rgw_replica_log.h"
38 #include "rgw_orphan.h"
39 #include "rgw_sync.h"
40 #include "rgw_data_sync.h"
41 #include "rgw_rest_conn.h"
42 #include "rgw_realm_watcher.h"
43 #include "rgw_role.h"
44
45 using namespace std;
46
47 #define dout_context g_ceph_context
48 #define dout_subsys ceph_subsys_rgw
49
50 #define SECRET_KEY_LEN 40
51 #define PUBLIC_ID_LEN 20
52
53 static RGWRados *store = NULL;
54
55 void _usage()
56 {
57 cout << "usage: radosgw-admin <cmd> [options...]" << std::endl;
58 cout << "commands:\n";
59 cout << " user create create a new user\n" ;
60 cout << " user modify modify user\n";
61 cout << " user info get user info\n";
62 cout << " user rm remove user\n";
63 cout << " user suspend suspend a user\n";
64 cout << " user enable re-enable user after suspension\n";
65 cout << " user check check user info\n";
66 cout << " user stats show user stats as accounted by quota subsystem\n";
67 cout << " user list list users\n";
68 cout << " caps add add user capabilities\n";
69 cout << " caps rm remove user capabilities\n";
70 cout << " subuser create create a new subuser\n" ;
71 cout << " subuser modify modify subuser\n";
72 cout << " subuser rm remove subuser\n";
73 cout << " key create create access key\n";
74 cout << " key rm remove access key\n";
75 cout << " bucket list list buckets\n";
76 cout << " bucket limit check show bucket sharding stats\n";
77 cout << " bucket link link bucket to specified user\n";
78 cout << " bucket unlink unlink bucket from specified user\n";
79 cout << " bucket stats returns bucket statistics\n";
80 cout << " bucket rm remove bucket\n";
81 cout << " bucket check check bucket index\n";
82 cout << " bucket reshard reshard bucket\n";
83 cout << " bi get retrieve bucket index object entries\n";
84 cout << " bi put store bucket index object entries\n";
85 cout << " bi list list raw bucket index entries\n";
86 cout << " object rm remove object\n";
87 cout << " object stat stat an object for its metadata\n";
88 cout << " object unlink unlink object from bucket index\n";
89 cout << " objects expire run expired objects cleanup\n";
90 cout << " period delete delete a period\n";
91 cout << " period get get period info\n";
92 cout << " period get-current get current period info\n";
93 cout << " period pull pull a period\n";
94 cout << " period push push a period\n";
95 cout << " period list list all periods\n";
96 cout << " period update update the staging period\n";
97 cout << " period commit commit the staging period\n";
98 cout << " quota set set quota params\n";
99 cout << " quota enable enable quota\n";
100 cout << " quota disable disable quota\n";
101 cout << " global quota get view global quota params\n";
102 cout << " global quota set set global quota params\n";
103 cout << " global quota enable enable a global quota\n";
104 cout << " global quota disable disable a global quota\n";
105 cout << " realm create create a new realm\n";
106 cout << " realm delete delete a realm\n";
107 cout << " realm get show realm info\n";
108 cout << " realm get-default get default realm name\n";
109 cout << " realm list list realms\n";
110 cout << " realm list-periods list all realm periods\n";
111 cout << " realm remove remove a zonegroup from the realm\n";
112 cout << " realm rename rename a realm\n";
113 cout << " realm set set realm info (requires infile)\n";
114 cout << " realm default set realm as default\n";
115 cout << " realm pull pull a realm and its current period\n";
116 cout << " zonegroup add add a zone to a zonegroup\n";
117 cout << " zonegroup create create a new zone group info\n";
118 cout << " zonegroup default set default zone group\n";
119 cout << " zonegroup delete delete a zone group info\n";
120 cout << " zonegroup get show zone group info\n";
121 cout << " zonegroup modify modify an existing zonegroup\n";
122 cout << " zonegroup set set zone group info (requires infile)\n";
123 cout << " zonegroup remove remove a zone from a zonegroup\n";
124 cout << " zonegroup rename rename a zone group\n";
125 cout << " zonegroup list list all zone groups set on this cluster\n";
126 cout << " zonegroup placement list list zonegroup's placement targets\n";
127 cout << " zonegroup placement add add a placement target id to a zonegroup\n";
128 cout << " zonegroup placement modify modify a placement target of a specific zonegroup\n";
129 cout << " zonegroup placement rm remove a placement target from a zonegroup\n";
130 cout << " zonegroup placement default set a zonegroup's default placement target\n";
131 cout << " zone create create a new zone\n";
132 cout << " zone delete delete a zone\n";
133 cout << " zone get show zone cluster params\n";
134 cout << " zone modify modify an existing zone\n";
135 cout << " zone set set zone cluster params (requires infile)\n";
136 cout << " zone list list all zones set on this cluster\n";
137 cout << " zone rename rename a zone\n";
138 cout << " zone placement list list zone's placement targets\n";
139 cout << " zone placement add add a zone placement target\n";
140 cout << " zone placement modify modify a zone placement target\n";
141 cout << " zone placement rm remove a zone placement target\n";
142 cout << " pool add add an existing pool for data placement\n";
143 cout << " pool rm remove an existing pool from data placement set\n";
144 cout << " pools list list placement active set\n";
145 cout << " policy read bucket/object policy\n";
146 cout << " log list list log objects\n";
147 cout << " log show dump a log from specific object or (bucket + date\n";
148 cout << " + bucket-id)\n";
149 cout << " (NOTE: required to specify formatting of date\n";
150 cout << " to \"YYYY-MM-DD-hh\")\n";
151 cout << " log rm remove log object\n";
152 cout << " usage show show usage (by user, date range)\n";
153 cout << " usage trim trim usage (by user, date range)\n";
154 cout << " gc list dump expired garbage collection objects (specify\n";
155 cout << " --include-all to list all entries, including unexpired)\n";
156 cout << " gc process manually process garbage\n";
157 cout << " lc list list all bucket lifecycle progress\n";
158 cout << " lc process manually process lifecycle\n";
159 cout << " metadata get get metadata info\n";
160 cout << " metadata put put metadata info\n";
161 cout << " metadata rm remove metadata info\n";
162 cout << " metadata list list metadata info\n";
163 cout << " mdlog list list metadata log\n";
164 cout << " mdlog trim trim metadata log (use start-date, end-date or\n";
165 cout << " start-marker, end-marker)\n";
166 cout << " mdlog status read metadata log status\n";
167 cout << " bilog list list bucket index log\n";
168 cout << " bilog trim trim bucket index log (use start-marker, end-marker)\n";
169 cout << " datalog list list data log\n";
170 cout << " datalog trim trim data log\n";
171 cout << " datalog status read data log status\n";
172 cout << " opstate list list stateful operations entries (use client_id,\n";
173 cout << " op_id, object)\n";
174 cout << " opstate set set state on an entry (use client_id, op_id, object, state)\n";
175 cout << " opstate renew renew state on an entry (use client_id, op_id, object)\n";
176 cout << " opstate rm remove entry (use client_id, op_id, object)\n";
177 cout << " replicalog get get replica metadata log entry\n";
178 cout << " replicalog update update replica metadata log entry\n";
179 cout << " replicalog delete delete replica metadata log entry\n";
180 cout << " orphans find init and run search for leaked rados objects (use job-id, pool)\n";
181 cout << " orphans finish clean up search for leaked rados objects\n";
182 cout << " orphans list-jobs list the current job-ids for orphans search\n";
183 cout << " role create create a AWS role for use with STS\n";
184 cout << " role delete delete a role\n";
185 cout << " role get get a role\n";
186 cout << " role list list roles with specified path prefix\n";
187 cout << " role modify modify the assume role policy of an existing role\n";
188 cout << " role-policy put add/update permission policy to role\n";
189 cout << " role-policy list list policies attached to a role\n";
190 cout << " role-policy get get the specified inline policy document embedded with the given role\n";
191 cout << " role-policy delete delete policy attached to a role\n";
192 cout << "options:\n";
193 cout << " --tenant=<tenant> tenant name\n";
194 cout << " --uid=<id> user id\n";
195 cout << " --subuser=<name> subuser name\n";
196 cout << " --access-key=<key> S3 access key\n";
197 cout << " --email=<email>\n";
198 cout << " --secret/--secret-key=<key>\n";
199 cout << " specify secret key\n";
200 cout << " --gen-access-key generate random access key (for S3)\n";
201 cout << " --gen-secret generate random secret key\n";
202 cout << " --key-type=<type> key type, options are: swift, s3\n";
203 cout << " --temp-url-key[-2]=<key> temp url key\n";
204 cout << " --access=<access> Set access permissions for sub-user, should be one\n";
205 cout << " of read, write, readwrite, full\n";
206 cout << " --display-name=<name>\n";
207 cout << " --max_buckets max number of buckets for a user\n";
208 cout << " --admin set the admin flag on the user\n";
209 cout << " --system set the system flag on the user\n";
210 cout << " --bucket=<bucket>\n";
211 cout << " --pool=<pool>\n";
212 cout << " --object=<object>\n";
213 cout << " --date=<date>\n";
214 cout << " --start-date=<date>\n";
215 cout << " --end-date=<date>\n";
216 cout << " --bucket-id=<bucket-id>\n";
217 cout << " --shard-id=<shard-id> optional for mdlog list\n";
218 cout << " required for: \n";
219 cout << " mdlog trim\n";
220 cout << " replica mdlog get/delete\n";
221 cout << " replica datalog get/delete\n";
222 cout << " --metadata-key=<key> key to retrieve metadata from with metadata get\n";
223 cout << " --remote=<remote> zone or zonegroup id of remote gateway\n";
224 cout << " --period=<id> period id\n";
225 cout << " --epoch=<number> period epoch\n";
226 cout << " --commit commit the period during 'period update'\n";
227 cout << " --staging get staging period info\n";
228 cout << " --master set as master\n";
229 cout << " --master-url master url\n";
230 cout << " --master-zonegroup=<id> master zonegroup id\n";
231 cout << " --master-zone=<id> master zone id\n";
232 cout << " --rgw-realm=<name> realm name\n";
233 cout << " --realm-id=<id> realm id\n";
234 cout << " --realm-new-name=<name> realm new name\n";
235 cout << " --rgw-zonegroup=<name> zonegroup name\n";
236 cout << " --zonegroup-id=<id> zonegroup id\n";
237 cout << " --zonegroup-new-name=<name>\n";
238 cout << " zonegroup new name\n";
239 cout << " --rgw-zone=<name> name of zone in which radosgw is running\n";
240 cout << " --zone-id=<id> zone id\n";
241 cout << " --zone-new-name=<name> zone new name\n";
242 cout << " --source-zone specify the source zone (for data sync)\n";
243 cout << " --default set entity (realm, zonegroup, zone) as default\n";
244 cout << " --read-only set zone as read-only (when adding to zonegroup)\n";
245 cout << " --placement-id placement id for zonegroup placement commands\n";
246 cout << " --tags=<list> list of tags for zonegroup placement add and modify commands\n";
247 cout << " --tags-add=<list> list of tags to add for zonegroup placement modify command\n";
248 cout << " --tags-rm=<list> list of tags to remove for zonegroup placement modify command\n";
249 cout << " --endpoints=<list> zone endpoints\n";
250 cout << " --index_pool=<pool> placement target index pool\n";
251 cout << " --data_pool=<pool> placement target data pool\n";
252 cout << " --data_extra_pool=<pool> placement target data extra (non-ec) pool\n";
253 cout << " --placement-index-type=<type>\n";
254 cout << " placement target index type (normal, indexless, or #id)\n";
255 cout << " --compression=<type> placement target compression type (plugin name or empty/none)\n";
256 cout << " --tier-type=<type> zone tier type\n";
257 cout << " --tier-config=<k>=<v>[,...]\n";
258 cout << " set zone tier config keys, values\n";
259 cout << " --tier-config-rm=<k>[,...]\n";
260 cout << " unset zone tier config keys\n";
261 cout << " --sync-from-all[=false] set/reset whether zone syncs from all zonegroup peers\n";
262 cout << " --sync-from=[zone-name][,...]\n";
263 cout << " set list of zones to sync from\n";
264 cout << " --sync-from-rm=[zone-name][,...]\n";
265 cout << " remove zones from list of zones to sync from\n";
266 cout << " --fix besides checking bucket index, will also fix it\n";
267 cout << " --check-objects bucket check: rebuilds bucket index according to\n";
268 cout << " actual objects state\n";
269 cout << " --format=<format> specify output format for certain operations: xml,\n";
270 cout << " json\n";
271 cout << " --purge-data when specified, user removal will also purge all the\n";
272 cout << " user data\n";
273 cout << " --purge-keys when specified, subuser removal will also purge all the\n";
274 cout << " subuser keys\n";
275 cout << " --purge-objects remove a bucket's objects before deleting it\n";
276 cout << " (NOTE: required to delete a non-empty bucket)\n";
277 cout << " --sync-stats option to 'user stats', update user stats with current\n";
278 cout << " stats reported by user's buckets indexes\n";
279 cout << " --show-log-entries=<flag> enable/disable dump of log entries on log show\n";
280 cout << " --show-log-sum=<flag> enable/disable dump of log summation on log show\n";
281 cout << " --skip-zero-entries log show only dumps entries that don't have zero value\n";
282 cout << " in one of the numeric field\n";
283 cout << " --infile=<file> specify a file to read in when setting data\n";
284 cout << " --state=<state string> specify a state for the opstate set command\n";
285 cout << " --replica-log-type replica log type (metadata, data, bucket), required for\n";
286 cout << " replica log operations\n";
287 cout << " --categories=<list> comma separated list of categories, used in usage show\n";
288 cout << " --caps=<caps> list of caps (e.g., \"usage=read, write; user=read\")\n";
289 cout << " --yes-i-really-mean-it required for certain operations\n";
290 cout << " --warnings-only when specified with bucket limit check, list\n";
291 cout << " only buckets nearing or over the current max\n";
292 cout << " objects per shard value\n";
293 cout << " --bypass-gc when specified with bucket deletion, triggers\n";
294 cout << " object deletions by not involving GC\n";
295 cout << " --inconsistent-index when specified with bucket deletion and bypass-gc set to true,\n";
296 cout << " ignores bucket index consistency\n";
297 cout << "\n";
298 cout << "<date> := \"YYYY-MM-DD[ hh:mm:ss]\"\n";
299 cout << "\nQuota options:\n";
300 cout << " --bucket specified bucket for quota command\n";
301 cout << " --max-objects specify max objects (negative value to disable)\n";
302 cout << " --max-size specify max size (in B/K/M/G/T, negative value to disable)\n";
303 cout << " --quota-scope scope of quota (bucket, user)\n";
304 cout << "\nOrphans search options:\n";
305 cout << " --pool data pool to scan for leaked rados objects in\n";
306 cout << " --num-shards num of shards to use for keeping the temporary scan info\n";
307 cout << " --orphan-stale-secs num of seconds to wait before declaring an object to be an orphan (default: 86400)\n";
308 cout << " --job-id set the job id (for orphans find)\n";
309 cout << " --max-concurrent-ios maximum concurrent ios for orphans find (default: 32)\n";
310 cout << "\nOrphans list-jobs options:\n";
311 cout << " --extra-info provide extra info in job list\n";
312 cout << "\nRole options:\n";
313 cout << " --role-name name of the role to create\n";
314 cout << " --path path to the role\n";
315 cout << " --assume-role-policy-doc the trust relationship policy document that grants an entity permission to assume the role\n";
316 cout << " --policy-name name of the policy document\n";
317 cout << " --policy-doc permission policy document\n";
318 cout << " --path-prefix path prefix for filtering roles\n";
319 cout << "\n";
320 generic_client_usage();
321 }
322
323 int usage()
324 {
325 _usage();
326 return 1;
327 }
328
329 enum {
330 OPT_NO_CMD = 0,
331 OPT_USER_CREATE,
332 OPT_USER_INFO,
333 OPT_USER_MODIFY,
334 OPT_USER_RM,
335 OPT_USER_SUSPEND,
336 OPT_USER_ENABLE,
337 OPT_USER_CHECK,
338 OPT_USER_STATS,
339 OPT_USER_LIST,
340 OPT_SUBUSER_CREATE,
341 OPT_SUBUSER_MODIFY,
342 OPT_SUBUSER_RM,
343 OPT_KEY_CREATE,
344 OPT_KEY_RM,
345 OPT_BUCKETS_LIST,
346 OPT_BUCKETS_LIMIT_CHECK,
347 OPT_BUCKET_LINK,
348 OPT_BUCKET_UNLINK,
349 OPT_BUCKET_STATS,
350 OPT_BUCKET_CHECK,
351 OPT_BUCKET_SYNC_STATUS,
352 OPT_BUCKET_SYNC_INIT,
353 OPT_BUCKET_SYNC_RUN,
354 OPT_BUCKET_RM,
355 OPT_BUCKET_REWRITE,
356 OPT_BUCKET_RESHARD,
357 OPT_POLICY,
358 OPT_POOL_ADD,
359 OPT_POOL_RM,
360 OPT_POOLS_LIST,
361 OPT_LOG_LIST,
362 OPT_LOG_SHOW,
363 OPT_LOG_RM,
364 OPT_USAGE_SHOW,
365 OPT_USAGE_TRIM,
366 OPT_OBJECT_RM,
367 OPT_OBJECT_UNLINK,
368 OPT_OBJECT_STAT,
369 OPT_OBJECT_REWRITE,
370 OPT_OBJECTS_EXPIRE,
371 OPT_BI_GET,
372 OPT_BI_PUT,
373 OPT_BI_LIST,
374 OPT_BI_PURGE,
375 OPT_OLH_GET,
376 OPT_OLH_READLOG,
377 OPT_QUOTA_SET,
378 OPT_QUOTA_ENABLE,
379 OPT_QUOTA_DISABLE,
380 OPT_GC_LIST,
381 OPT_GC_PROCESS,
382 OPT_LC_LIST,
383 OPT_LC_PROCESS,
384 OPT_ORPHANS_FIND,
385 OPT_ORPHANS_FINISH,
386 OPT_ORPHANS_LIST_JOBS,
387 OPT_ZONEGROUP_ADD,
388 OPT_ZONEGROUP_CREATE,
389 OPT_ZONEGROUP_DEFAULT,
390 OPT_ZONEGROUP_DELETE,
391 OPT_ZONEGROUP_GET,
392 OPT_ZONEGROUP_MODIFY,
393 OPT_ZONEGROUP_SET,
394 OPT_ZONEGROUP_LIST,
395 OPT_ZONEGROUP_REMOVE,
396 OPT_ZONEGROUP_RENAME,
397 OPT_ZONEGROUP_PLACEMENT_ADD,
398 OPT_ZONEGROUP_PLACEMENT_MODIFY,
399 OPT_ZONEGROUP_PLACEMENT_RM,
400 OPT_ZONEGROUP_PLACEMENT_LIST,
401 OPT_ZONEGROUP_PLACEMENT_DEFAULT,
402 OPT_ZONE_CREATE,
403 OPT_ZONE_DELETE,
404 OPT_ZONE_GET,
405 OPT_ZONE_MODIFY,
406 OPT_ZONE_SET,
407 OPT_ZONE_LIST,
408 OPT_ZONE_RENAME,
409 OPT_ZONE_DEFAULT,
410 OPT_ZONE_PLACEMENT_ADD,
411 OPT_ZONE_PLACEMENT_MODIFY,
412 OPT_ZONE_PLACEMENT_RM,
413 OPT_ZONE_PLACEMENT_LIST,
414 OPT_CAPS_ADD,
415 OPT_CAPS_RM,
416 OPT_METADATA_GET,
417 OPT_METADATA_PUT,
418 OPT_METADATA_RM,
419 OPT_METADATA_LIST,
420 OPT_METADATA_SYNC_STATUS,
421 OPT_METADATA_SYNC_INIT,
422 OPT_METADATA_SYNC_RUN,
423 OPT_MDLOG_LIST,
424 OPT_MDLOG_AUTOTRIM,
425 OPT_MDLOG_TRIM,
426 OPT_MDLOG_FETCH,
427 OPT_MDLOG_STATUS,
428 OPT_SYNC_ERROR_LIST,
429 OPT_BILOG_LIST,
430 OPT_BILOG_TRIM,
431 OPT_BILOG_STATUS,
432 OPT_DATA_SYNC_STATUS,
433 OPT_DATA_SYNC_INIT,
434 OPT_DATA_SYNC_RUN,
435 OPT_DATALOG_LIST,
436 OPT_DATALOG_STATUS,
437 OPT_DATALOG_TRIM,
438 OPT_OPSTATE_LIST,
439 OPT_OPSTATE_SET,
440 OPT_OPSTATE_RENEW,
441 OPT_OPSTATE_RM,
442 OPT_REPLICALOG_GET,
443 OPT_REPLICALOG_UPDATE,
444 OPT_REPLICALOG_DELETE,
445 OPT_REALM_CREATE,
446 OPT_REALM_DELETE,
447 OPT_REALM_GET,
448 OPT_REALM_GET_DEFAULT,
449 OPT_REALM_LIST,
450 OPT_REALM_LIST_PERIODS,
451 OPT_REALM_REMOVE,
452 OPT_REALM_RENAME,
453 OPT_REALM_SET,
454 OPT_REALM_DEFAULT,
455 OPT_REALM_PULL,
456 OPT_PERIOD_DELETE,
457 OPT_PERIOD_GET,
458 OPT_PERIOD_GET_CURRENT,
459 OPT_PERIOD_PULL,
460 OPT_PERIOD_PUSH,
461 OPT_PERIOD_LIST,
462 OPT_PERIOD_UPDATE,
463 OPT_PERIOD_COMMIT,
464 OPT_GLOBAL_QUOTA_GET,
465 OPT_GLOBAL_QUOTA_SET,
466 OPT_GLOBAL_QUOTA_ENABLE,
467 OPT_GLOBAL_QUOTA_DISABLE,
468 OPT_SYNC_STATUS,
469 OPT_ROLE_CREATE,
470 OPT_ROLE_DELETE,
471 OPT_ROLE_GET,
472 OPT_ROLE_MODIFY,
473 OPT_ROLE_LIST,
474 OPT_ROLE_POLICY_PUT,
475 OPT_ROLE_POLICY_LIST,
476 OPT_ROLE_POLICY_GET,
477 OPT_ROLE_POLICY_DELETE,
478 };
479
480 static int get_cmd(const char *cmd, const char *prev_cmd, const char *prev_prev_cmd, bool *need_more)
481 {
482 *need_more = false;
483 // NOTE: please keep the checks in alphabetical order !!!
484 if (strcmp(cmd, "bi") == 0 ||
485 strcmp(cmd, "bilog") == 0 ||
486 strcmp(cmd, "bucket") == 0 ||
487 strcmp(cmd, "buckets") == 0 ||
488 strcmp(cmd, "caps") == 0 ||
489 strcmp(cmd, "data") == 0 ||
490 strcmp(cmd, "datalog") == 0 ||
491 strcmp(cmd, "error") == 0 ||
492 strcmp(cmd, "gc") == 0 ||
493 strcmp(cmd, "global") == 0 ||
494 strcmp(cmd, "key") == 0 ||
495 strcmp(cmd, "log") == 0 ||
496 strcmp(cmd, "lc") == 0 ||
497 strcmp(cmd, "mdlog") == 0 ||
498 strcmp(cmd, "metadata") == 0 ||
499 strcmp(cmd, "object") == 0 ||
500 strcmp(cmd, "objects") == 0 ||
501 strcmp(cmd, "olh") == 0 ||
502 strcmp(cmd, "opstate") == 0 ||
503 strcmp(cmd, "orphans") == 0 ||
504 strcmp(cmd, "period") == 0 ||
505 strcmp(cmd, "placement") == 0 ||
506 strcmp(cmd, "pool") == 0 ||
507 strcmp(cmd, "pools") == 0 ||
508 strcmp(cmd, "quota") == 0 ||
509 strcmp(cmd, "realm") == 0 ||
510 strcmp(cmd, "replicalog") == 0 ||
511 strcmp(cmd, "role") == 0 ||
512 strcmp(cmd, "role-policy") == 0 ||
513 strcmp(cmd, "subuser") == 0 ||
514 strcmp(cmd, "sync") == 0 ||
515 strcmp(cmd, "usage") == 0 ||
516 strcmp(cmd, "user") == 0 ||
517 strcmp(cmd, "zone") == 0 ||
518 strcmp(cmd, "zonegroup") == 0 ||
519 strcmp(cmd, "zonegroups") == 0)
520 {
521 *need_more = true;
522 return 0;
523 }
524
525 if (strcmp(cmd, "policy") == 0)
526 return OPT_POLICY;
527
528 if (!prev_cmd)
529 return -EINVAL;
530
531 if (strcmp(prev_cmd, "user") == 0) {
532 if (strcmp(cmd, "create") == 0)
533 return OPT_USER_CREATE;
534 if (strcmp(cmd, "info") == 0)
535 return OPT_USER_INFO;
536 if (strcmp(cmd, "modify") == 0)
537 return OPT_USER_MODIFY;
538 if (strcmp(cmd, "rm") == 0)
539 return OPT_USER_RM;
540 if (strcmp(cmd, "suspend") == 0)
541 return OPT_USER_SUSPEND;
542 if (strcmp(cmd, "enable") == 0)
543 return OPT_USER_ENABLE;
544 if (strcmp(cmd, "check") == 0)
545 return OPT_USER_CHECK;
546 if (strcmp(cmd, "stats") == 0)
547 return OPT_USER_STATS;
548 if (strcmp(cmd, "list") == 0)
549 return OPT_USER_LIST;
550 } else if (strcmp(prev_cmd, "subuser") == 0) {
551 if (strcmp(cmd, "create") == 0)
552 return OPT_SUBUSER_CREATE;
553 if (strcmp(cmd, "modify") == 0)
554 return OPT_SUBUSER_MODIFY;
555 if (strcmp(cmd, "rm") == 0)
556 return OPT_SUBUSER_RM;
557 } else if (strcmp(prev_cmd, "key") == 0) {
558 if (strcmp(cmd, "create") == 0)
559 return OPT_KEY_CREATE;
560 if (strcmp(cmd, "rm") == 0)
561 return OPT_KEY_RM;
562 } else if (strcmp(prev_cmd, "buckets") == 0) {
563 if (strcmp(cmd, "list") == 0)
564 return OPT_BUCKETS_LIST;
565 if (strcmp(cmd, "limit") == 0) {
566 *need_more = true;
567 return 0;
568 }
569 } else if (strcmp(prev_cmd, "bucket") == 0) {
570 if (strcmp(cmd, "list") == 0)
571 return OPT_BUCKETS_LIST;
572 if (strcmp(cmd, "link") == 0)
573 return OPT_BUCKET_LINK;
574 if (strcmp(cmd, "unlink") == 0)
575 return OPT_BUCKET_UNLINK;
576 if (strcmp(cmd, "stats") == 0)
577 return OPT_BUCKET_STATS;
578 if (strcmp(cmd, "rm") == 0)
579 return OPT_BUCKET_RM;
580 if (strcmp(cmd, "rewrite") == 0)
581 return OPT_BUCKET_REWRITE;
582 if (strcmp(cmd, "reshard") == 0)
583 return OPT_BUCKET_RESHARD;
584 if (strcmp(cmd, "check") == 0)
585 return OPT_BUCKET_CHECK;
586 if (strcmp(cmd, "sync") == 0) {
587 *need_more = true;
588 return 0;
589 }
590 } else if (prev_prev_cmd && strcmp(prev_prev_cmd, "bucket") == 0) {
591 if (strcmp(prev_cmd, "sync") == 0) {
592 if (strcmp(cmd, "status") == 0)
593 return OPT_BUCKET_SYNC_STATUS;
594 if (strcmp(cmd, "init") == 0)
595 return OPT_BUCKET_SYNC_INIT;
596 if (strcmp(cmd, "run") == 0)
597 return OPT_BUCKET_SYNC_RUN;
598 } else if ((strcmp(prev_cmd, "limit") == 0) &&
599 (strcmp(cmd, "check") == 0)) {
600 return OPT_BUCKETS_LIMIT_CHECK;
601 }
602 } else if (strcmp(prev_cmd, "log") == 0) {
603 if (strcmp(cmd, "list") == 0)
604 return OPT_LOG_LIST;
605 if (strcmp(cmd, "show") == 0)
606 return OPT_LOG_SHOW;
607 if (strcmp(cmd, "rm") == 0)
608 return OPT_LOG_RM;
609 } else if (strcmp(prev_cmd, "usage") == 0) {
610 if (strcmp(cmd, "show") == 0)
611 return OPT_USAGE_SHOW;
612 if (strcmp(cmd, "trim") == 0)
613 return OPT_USAGE_TRIM;
614 } else if (strcmp(prev_cmd, "caps") == 0) {
615 if (strcmp(cmd, "add") == 0)
616 return OPT_CAPS_ADD;
617 if (strcmp(cmd, "rm") == 0)
618 return OPT_CAPS_RM;
619 } else if (strcmp(prev_cmd, "pool") == 0) {
620 if (strcmp(cmd, "add") == 0)
621 return OPT_POOL_ADD;
622 if (strcmp(cmd, "rm") == 0)
623 return OPT_POOL_RM;
624 if (strcmp(cmd, "list") == 0)
625 return OPT_POOLS_LIST;
626 } else if (strcmp(prev_cmd, "pools") == 0) {
627 if (strcmp(cmd, "list") == 0)
628 return OPT_POOLS_LIST;
629 } else if (strcmp(prev_cmd, "object") == 0) {
630 if (strcmp(cmd, "rm") == 0)
631 return OPT_OBJECT_RM;
632 if (strcmp(cmd, "unlink") == 0)
633 return OPT_OBJECT_UNLINK;
634 if (strcmp(cmd, "stat") == 0)
635 return OPT_OBJECT_STAT;
636 if (strcmp(cmd, "rewrite") == 0)
637 return OPT_OBJECT_REWRITE;
638 } else if (strcmp(prev_cmd, "objects") == 0) {
639 if (strcmp(cmd, "expire") == 0)
640 return OPT_OBJECTS_EXPIRE;
641 } else if (strcmp(prev_cmd, "olh") == 0) {
642 if (strcmp(cmd, "get") == 0)
643 return OPT_OLH_GET;
644 if (strcmp(cmd, "readlog") == 0)
645 return OPT_OLH_READLOG;
646 } else if (strcmp(prev_cmd, "bi") == 0) {
647 if (strcmp(cmd, "get") == 0)
648 return OPT_BI_GET;
649 if (strcmp(cmd, "put") == 0)
650 return OPT_BI_PUT;
651 if (strcmp(cmd, "list") == 0)
652 return OPT_BI_LIST;
653 if (strcmp(cmd, "purge") == 0)
654 return OPT_BI_PURGE;
655 } else if ((prev_prev_cmd && strcmp(prev_prev_cmd, "global") == 0) &&
656 (strcmp(prev_cmd, "quota") == 0)) {
657 if (strcmp(cmd, "get") == 0)
658 return OPT_GLOBAL_QUOTA_GET;
659 if (strcmp(cmd, "set") == 0)
660 return OPT_GLOBAL_QUOTA_SET;
661 if (strcmp(cmd, "enable") == 0)
662 return OPT_GLOBAL_QUOTA_ENABLE;
663 if (strcmp(cmd, "disable") == 0)
664 return OPT_GLOBAL_QUOTA_DISABLE;
665 } else if (strcmp(prev_cmd, "period") == 0) {
666 if (strcmp(cmd, "delete") == 0)
667 return OPT_PERIOD_DELETE;
668 if (strcmp(cmd, "get") == 0)
669 return OPT_PERIOD_GET;
670 if (strcmp(cmd, "get-current") == 0)
671 return OPT_PERIOD_GET_CURRENT;
672 if (strcmp(cmd, "pull") == 0)
673 return OPT_PERIOD_PULL;
674 if (strcmp(cmd, "push") == 0)
675 return OPT_PERIOD_PUSH;
676 if (strcmp(cmd, "list") == 0)
677 return OPT_PERIOD_LIST;
678 if (strcmp(cmd, "update") == 0)
679 return OPT_PERIOD_UPDATE;
680 if (strcmp(cmd, "commit") == 0)
681 return OPT_PERIOD_COMMIT;
682 } else if (strcmp(prev_cmd, "realm") == 0) {
683 if (strcmp(cmd, "create") == 0)
684 return OPT_REALM_CREATE;
685 if (strcmp(cmd, "delete") == 0)
686 return OPT_REALM_DELETE;
687 if (strcmp(cmd, "get") == 0)
688 return OPT_REALM_GET;
689 if (strcmp(cmd, "get-default") == 0)
690 return OPT_REALM_GET_DEFAULT;
691 if (strcmp(cmd, "list") == 0)
692 return OPT_REALM_LIST;
693 if (strcmp(cmd, "list-periods") == 0)
694 return OPT_REALM_LIST_PERIODS;
695 if (strcmp(cmd, "remove") == 0)
696 return OPT_REALM_REMOVE;
697 if (strcmp(cmd, "rename") == 0)
698 return OPT_REALM_RENAME;
699 if (strcmp(cmd, "set") == 0)
700 return OPT_REALM_SET;
701 if (strcmp(cmd, "default") == 0)
702 return OPT_REALM_DEFAULT;
703 if (strcmp(cmd, "pull") == 0)
704 return OPT_REALM_PULL;
705 } else if ((prev_prev_cmd && strcmp(prev_prev_cmd, "zonegroup") == 0) &&
706 (strcmp(prev_cmd, "placement") == 0)) {
707 if (strcmp(cmd, "add") == 0)
708 return OPT_ZONEGROUP_PLACEMENT_ADD;
709 if (strcmp(cmd, "modify") == 0)
710 return OPT_ZONEGROUP_PLACEMENT_MODIFY;
711 if (strcmp(cmd, "rm") == 0)
712 return OPT_ZONEGROUP_PLACEMENT_RM;
713 if (strcmp(cmd, "list") == 0)
714 return OPT_ZONEGROUP_PLACEMENT_LIST;
715 if (strcmp(cmd, "default") == 0)
716 return OPT_ZONEGROUP_PLACEMENT_DEFAULT;
717 } else if (strcmp(prev_cmd, "zonegroup") == 0) {
718 if (strcmp(cmd, "add") == 0)
719 return OPT_ZONEGROUP_ADD;
720 if (strcmp(cmd, "create")== 0)
721 return OPT_ZONEGROUP_CREATE;
722 if (strcmp(cmd, "default") == 0)
723 return OPT_ZONEGROUP_DEFAULT;
724 if (strcmp(cmd, "delete") == 0)
725 return OPT_ZONEGROUP_DELETE;
726 if (strcmp(cmd, "get") == 0)
727 return OPT_ZONEGROUP_GET;
728 if (strcmp(cmd, "modify") == 0)
729 return OPT_ZONEGROUP_MODIFY;
730 if (strcmp(cmd, "list") == 0)
731 return OPT_ZONEGROUP_LIST;
732 if (strcmp(cmd, "set") == 0)
733 return OPT_ZONEGROUP_SET;
734 if (strcmp(cmd, "remove") == 0)
735 return OPT_ZONEGROUP_REMOVE;
736 if (strcmp(cmd, "rename") == 0)
737 return OPT_ZONEGROUP_RENAME;
738 } else if (strcmp(prev_cmd, "quota") == 0) {
739 if (strcmp(cmd, "set") == 0)
740 return OPT_QUOTA_SET;
741 if (strcmp(cmd, "enable") == 0)
742 return OPT_QUOTA_ENABLE;
743 if (strcmp(cmd, "disable") == 0)
744 return OPT_QUOTA_DISABLE;
745 } else if (strcmp(prev_cmd, "zonegroups") == 0) {
746 if (strcmp(cmd, "list") == 0)
747 return OPT_ZONEGROUP_LIST;
748 } else if ((prev_prev_cmd && strcmp(prev_prev_cmd, "zone") == 0) &&
749 (strcmp(prev_cmd, "placement") == 0)) {
750 if (strcmp(cmd, "add") == 0)
751 return OPT_ZONE_PLACEMENT_ADD;
752 if (strcmp(cmd, "modify") == 0)
753 return OPT_ZONE_PLACEMENT_MODIFY;
754 if (strcmp(cmd, "rm") == 0)
755 return OPT_ZONE_PLACEMENT_RM;
756 if (strcmp(cmd, "list") == 0)
757 return OPT_ZONE_PLACEMENT_LIST;
758 } else if (strcmp(prev_cmd, "zone") == 0) {
759 if (strcmp(cmd, "delete") == 0)
760 return OPT_ZONE_DELETE;
761 if (strcmp(cmd, "create") == 0)
762 return OPT_ZONE_CREATE;
763 if (strcmp(cmd, "get") == 0)
764 return OPT_ZONE_GET;
765 if (strcmp(cmd, "set") == 0)
766 return OPT_ZONE_SET;
767 if (strcmp(cmd, "list") == 0)
768 return OPT_ZONE_LIST;
769 if (strcmp(cmd, "modify") == 0)
770 return OPT_ZONE_MODIFY;
771 if (strcmp(cmd, "rename") == 0)
772 return OPT_ZONE_RENAME;
773 if (strcmp(cmd, "default") == 0)
774 return OPT_ZONE_DEFAULT;
775 } else if (strcmp(prev_cmd, "zones") == 0) {
776 if (strcmp(cmd, "list") == 0)
777 return OPT_ZONE_LIST;
778 } else if (strcmp(prev_cmd, "gc") == 0) {
779 if (strcmp(cmd, "list") == 0)
780 return OPT_GC_LIST;
781 if (strcmp(cmd, "process") == 0)
782 return OPT_GC_PROCESS;
783 } else if (strcmp(prev_cmd, "lc") == 0) {
784 if (strcmp(cmd, "list") == 0)
785 return OPT_LC_LIST;
786 if (strcmp(cmd, "process") == 0)
787 return OPT_LC_PROCESS;
788 } else if (strcmp(prev_cmd, "orphans") == 0) {
789 if (strcmp(cmd, "find") == 0)
790 return OPT_ORPHANS_FIND;
791 if (strcmp(cmd, "finish") == 0)
792 return OPT_ORPHANS_FINISH;
793 if (strcmp(cmd, "list-jobs") == 0)
794 return OPT_ORPHANS_LIST_JOBS;
795 } else if (strcmp(prev_cmd, "metadata") == 0) {
796 if (strcmp(cmd, "get") == 0)
797 return OPT_METADATA_GET;
798 if (strcmp(cmd, "put") == 0)
799 return OPT_METADATA_PUT;
800 if (strcmp(cmd, "rm") == 0)
801 return OPT_METADATA_RM;
802 if (strcmp(cmd, "list") == 0)
803 return OPT_METADATA_LIST;
804 if (strcmp(cmd, "sync") == 0) {
805 *need_more = true;
806 return 0;
807 }
808 } else if ((prev_prev_cmd && strcmp(prev_prev_cmd, "metadata") == 0) &&
809 (strcmp(prev_cmd, "sync") == 0)) {
810 if (strcmp(cmd, "status") == 0)
811 return OPT_METADATA_SYNC_STATUS;
812 if (strcmp(cmd, "init") == 0)
813 return OPT_METADATA_SYNC_INIT;
814 if (strcmp(cmd, "run") == 0)
815 return OPT_METADATA_SYNC_RUN;
816 } else if ((prev_prev_cmd && strcmp(prev_prev_cmd, "sync") == 0) &&
817 (strcmp(prev_cmd, "error") == 0)) {
818 if (strcmp(cmd, "list") == 0)
819 return OPT_SYNC_ERROR_LIST;
820 } else if (strcmp(prev_cmd, "mdlog") == 0) {
821 if (strcmp(cmd, "list") == 0)
822 return OPT_MDLOG_LIST;
823 if (strcmp(cmd, "autotrim") == 0)
824 return OPT_MDLOG_AUTOTRIM;
825 if (strcmp(cmd, "trim") == 0)
826 return OPT_MDLOG_TRIM;
827 if (strcmp(cmd, "fetch") == 0)
828 return OPT_MDLOG_FETCH;
829 if (strcmp(cmd, "status") == 0)
830 return OPT_MDLOG_STATUS;
831 } else if (strcmp(prev_cmd, "bilog") == 0) {
832 if (strcmp(cmd, "list") == 0)
833 return OPT_BILOG_LIST;
834 if (strcmp(cmd, "trim") == 0)
835 return OPT_BILOG_TRIM;
836 if (strcmp(cmd, "status") == 0)
837 return OPT_BILOG_STATUS;
838 } else if (strcmp(prev_cmd, "data") == 0) {
839 if (strcmp(cmd, "sync") == 0) {
840 *need_more = true;
841 return 0;
842 }
843 } else if (strcmp(prev_cmd, "datalog") == 0) {
844 if (strcmp(cmd, "list") == 0)
845 return OPT_DATALOG_LIST;
846 if (strcmp(cmd, "trim") == 0)
847 return OPT_DATALOG_TRIM;
848 if (strcmp(cmd, "status") == 0)
849 return OPT_DATALOG_STATUS;
850 } else if ((prev_prev_cmd && strcmp(prev_prev_cmd, "data") == 0) &&
851 (strcmp(prev_cmd, "sync") == 0)) {
852 if (strcmp(cmd, "status") == 0)
853 return OPT_DATA_SYNC_STATUS;
854 if (strcmp(cmd, "init") == 0)
855 return OPT_DATA_SYNC_INIT;
856 if (strcmp(cmd, "run") == 0)
857 return OPT_DATA_SYNC_RUN;
858 } else if (strcmp(prev_cmd, "opstate") == 0) {
859 if (strcmp(cmd, "list") == 0)
860 return OPT_OPSTATE_LIST;
861 if (strcmp(cmd, "set") == 0)
862 return OPT_OPSTATE_SET;
863 if (strcmp(cmd, "renew") == 0)
864 return OPT_OPSTATE_RENEW;
865 if (strcmp(cmd, "rm") == 0)
866 return OPT_OPSTATE_RM;
867 } else if (strcmp(prev_cmd, "replicalog") == 0) {
868 if (strcmp(cmd, "get") == 0)
869 return OPT_REPLICALOG_GET;
870 if (strcmp(cmd, "update") == 0)
871 return OPT_REPLICALOG_UPDATE;
872 if (strcmp(cmd, "delete") == 0)
873 return OPT_REPLICALOG_DELETE;
874 } else if (strcmp(prev_cmd, "sync") == 0) {
875 if (strcmp(cmd, "status") == 0)
876 return OPT_SYNC_STATUS;
877 } else if (strcmp(prev_cmd, "role") == 0) {
878 if (strcmp(cmd, "create") == 0)
879 return OPT_ROLE_CREATE;
880 if (strcmp(cmd, "delete") == 0)
881 return OPT_ROLE_DELETE;
882 if (strcmp(cmd, "get") == 0)
883 return OPT_ROLE_GET;
884 if (strcmp(cmd, "modify") == 0)
885 return OPT_ROLE_MODIFY;
886 if (strcmp(cmd, "list") == 0)
887 return OPT_ROLE_LIST;
888 } else if (strcmp(prev_cmd, "role-policy") == 0) {
889 if (strcmp(cmd, "put") == 0)
890 return OPT_ROLE_POLICY_PUT;
891 if (strcmp(cmd, "list") == 0)
892 return OPT_ROLE_POLICY_LIST;
893 if (strcmp(cmd, "get") == 0)
894 return OPT_ROLE_POLICY_GET;
895 if (strcmp(cmd, "delete") == 0)
896 return OPT_ROLE_POLICY_DELETE;
897 }
898
899 return -EINVAL;
900 }
901
902 enum ReplicaLogType {
903 ReplicaLog_Invalid = 0,
904 ReplicaLog_Metadata,
905 ReplicaLog_Data,
906 ReplicaLog_Bucket,
907 };
908
909 ReplicaLogType get_replicalog_type(const string& name) {
910 if (name == "md" || name == "meta" || name == "metadata")
911 return ReplicaLog_Metadata;
912 if (name == "data")
913 return ReplicaLog_Data;
914 if (name == "bucket")
915 return ReplicaLog_Bucket;
916
917 return ReplicaLog_Invalid;
918 }
919
920 BIIndexType get_bi_index_type(const string& type_str) {
921 if (type_str == "plain")
922 return PlainIdx;
923 if (type_str == "instance")
924 return InstanceIdx;
925 if (type_str == "olh")
926 return OLHIdx;
927
928 return InvalidIdx;
929 }
930
931 void dump_bi_entry(bufferlist& bl, BIIndexType index_type, Formatter *formatter)
932 {
933 bufferlist::iterator iter = bl.begin();
934 switch (index_type) {
935 case PlainIdx:
936 case InstanceIdx:
937 {
938 rgw_bucket_dir_entry entry;
939 ::decode(entry, iter);
940 encode_json("entry", entry, formatter);
941 }
942 break;
943 case OLHIdx:
944 {
945 rgw_bucket_olh_entry entry;
946 ::decode(entry, iter);
947 encode_json("entry", entry, formatter);
948 }
949 break;
950 default:
951 ceph_abort();
952 break;
953 }
954 }
955
956 static void show_user_info(RGWUserInfo& info, Formatter *formatter)
957 {
958 encode_json("user_info", info, formatter);
959 formatter->flush(cout);
960 cout << std::endl;
961 }
962
963 static void show_perm_policy(string perm_policy, Formatter* formatter)
964 {
965 formatter->open_object_section("role");
966 formatter->dump_string("Permission policy", perm_policy);
967 formatter->close_section();
968 formatter->flush(cout);
969 }
970
971 static void show_policy_names(std::vector<string> policy_names, Formatter* formatter)
972 {
973 formatter->open_array_section("PolicyNames");
974 for (const auto& it : policy_names) {
975 formatter->dump_string("policyname", it);
976 }
977 formatter->close_section();
978 formatter->flush(cout);
979 }
980
981 static void show_role_info(RGWRole& role, Formatter* formatter)
982 {
983 formatter->open_object_section("role");
984 role.dump(formatter);
985 formatter->close_section();
986 formatter->flush(cout);
987 }
988
989 static void show_roles_info(vector<RGWRole>& roles, Formatter* formatter)
990 {
991 formatter->open_array_section("Roles");
992 for (const auto& it : roles) {
993 formatter->open_object_section("role");
994 it.dump(formatter);
995 formatter->close_section();
996 }
997 formatter->close_section();
998 formatter->flush(cout);
999 }
1000
1001 static void dump_bucket_usage(map<RGWObjCategory, RGWStorageStats>& stats, Formatter *formatter)
1002 {
1003 map<RGWObjCategory, RGWStorageStats>::iterator iter;
1004
1005 formatter->open_object_section("usage");
1006 for (iter = stats.begin(); iter != stats.end(); ++iter) {
1007 RGWStorageStats& s = iter->second;
1008 const char *cat_name = rgw_obj_category_name(iter->first);
1009 formatter->open_object_section(cat_name);
1010 formatter->dump_int("size", s.size);
1011 formatter->dump_int("size_actual", s.size_rounded);
1012 formatter->dump_int("size_kb", rgw_rounded_kb(s.size));
1013 formatter->dump_int("size_kb_actual", rgw_rounded_kb(s.size_rounded));
1014 formatter->dump_int("num_objects", s.num_objects);
1015 formatter->close_section();
1016 formatter->flush(cout);
1017 }
1018 formatter->close_section();
1019 }
1020
1021 int bucket_stats(rgw_bucket& bucket, int shard_id, Formatter *formatter)
1022 {
1023 RGWBucketInfo bucket_info;
1024 real_time mtime;
1025 RGWObjectCtx obj_ctx(store);
1026 int r = store->get_bucket_info(obj_ctx, bucket.tenant, bucket.name, bucket_info, &mtime);
1027 if (r < 0)
1028 return r;
1029
1030 map<RGWObjCategory, RGWStorageStats> stats;
1031 string bucket_ver, master_ver;
1032 string max_marker;
1033 int ret = store->get_bucket_stats(bucket_info, shard_id, &bucket_ver, &master_ver, stats, &max_marker);
1034 if (ret < 0) {
1035 cerr << "error getting bucket stats ret=" << ret << std::endl;
1036 return ret;
1037 }
1038 formatter->open_object_section("stats");
1039 formatter->dump_string("bucket", bucket.name);
1040 ::encode_json("explicit_placement", bucket.explicit_placement, formatter);
1041
1042 formatter->dump_string("id", bucket.bucket_id);
1043 formatter->dump_string("marker", bucket.marker);
1044 formatter->dump_stream("index_type") << bucket_info.index_type;
1045 ::encode_json("owner", bucket_info.owner, formatter);
1046 formatter->dump_int("mtime", utime_t(mtime));
1047 formatter->dump_string("ver", bucket_ver);
1048 formatter->dump_string("master_ver", master_ver);
1049 formatter->dump_string("max_marker", max_marker);
1050 dump_bucket_usage(stats, formatter);
1051 formatter->close_section();
1052
1053 return 0;
1054 }
1055
1056 class StoreDestructor {
1057 RGWRados *store;
1058 public:
1059 explicit StoreDestructor(RGWRados *_s) : store(_s) {}
1060 ~StoreDestructor() {
1061 RGWStoreManager::close_storage(store);
1062 }
1063 };
1064
1065 static int init_bucket(const string& tenant_name, const string& bucket_name, const string& bucket_id,
1066 RGWBucketInfo& bucket_info, rgw_bucket& bucket, map<string, bufferlist> *pattrs = nullptr)
1067 {
1068 if (!bucket_name.empty()) {
1069 RGWObjectCtx obj_ctx(store);
1070 int r;
1071 if (bucket_id.empty()) {
1072 r = store->get_bucket_info(obj_ctx, tenant_name, bucket_name, bucket_info, nullptr, pattrs);
1073 } else {
1074 string bucket_instance_id = bucket_name + ":" + bucket_id;
1075 r = store->get_bucket_instance_info(obj_ctx, bucket_instance_id, bucket_info, NULL, pattrs);
1076 }
1077 if (r < 0) {
1078 cerr << "could not get bucket info for bucket=" << bucket_name << std::endl;
1079 return r;
1080 }
1081 bucket = bucket_info.bucket;
1082 }
1083 return 0;
1084 }
1085
1086 static int read_input(const string& infile, bufferlist& bl)
1087 {
1088 int fd = 0;
1089 if (infile.size()) {
1090 fd = open(infile.c_str(), O_RDONLY);
1091 if (fd < 0) {
1092 int err = -errno;
1093 cerr << "error reading input file " << infile << std::endl;
1094 return err;
1095 }
1096 }
1097
1098 #define READ_CHUNK 8196
1099 int r;
1100 int err;
1101
1102 do {
1103 char buf[READ_CHUNK];
1104
1105 r = safe_read(fd, buf, READ_CHUNK);
1106 if (r < 0) {
1107 err = -errno;
1108 cerr << "error while reading input" << std::endl;
1109 goto out;
1110 }
1111 bl.append(buf, r);
1112 } while (r > 0);
1113 err = 0;
1114
1115 out:
1116 if (infile.size()) {
1117 close(fd);
1118 }
1119 return err;
1120 }
1121
1122 template <class T>
1123 static int read_decode_json(const string& infile, T& t)
1124 {
1125 bufferlist bl;
1126 int ret = read_input(infile, bl);
1127 if (ret < 0) {
1128 cerr << "ERROR: failed to read input: " << cpp_strerror(-ret) << std::endl;
1129 return ret;
1130 }
1131 JSONParser p;
1132 if (!p.parse(bl.c_str(), bl.length())) {
1133 cout << "failed to parse JSON" << std::endl;
1134 return -EINVAL;
1135 }
1136
1137 try {
1138 decode_json_obj(t, &p);
1139 } catch (JSONDecoder::err& e) {
1140 cout << "failed to decode JSON input: " << e.message << std::endl;
1141 return -EINVAL;
1142 }
1143 return 0;
1144 }
1145
1146 template <class T, class K>
1147 static int read_decode_json(const string& infile, T& t, K *k)
1148 {
1149 bufferlist bl;
1150 int ret = read_input(infile, bl);
1151 if (ret < 0) {
1152 cerr << "ERROR: failed to read input: " << cpp_strerror(-ret) << std::endl;
1153 return ret;
1154 }
1155 JSONParser p;
1156 if (!p.parse(bl.c_str(), bl.length())) {
1157 cout << "failed to parse JSON" << std::endl;
1158 return -EINVAL;
1159 }
1160
1161 try {
1162 t.decode_json(&p, k);
1163 } catch (JSONDecoder::err& e) {
1164 cout << "failed to decode JSON input: " << e.message << std::endl;
1165 return -EINVAL;
1166 }
1167 return 0;
1168 }
1169
1170 static int parse_date_str(const string& date_str, utime_t& ut)
1171 {
1172 uint64_t epoch = 0;
1173 uint64_t nsec = 0;
1174
1175 if (!date_str.empty()) {
1176 int ret = utime_t::parse_date(date_str, &epoch, &nsec);
1177 if (ret < 0) {
1178 cerr << "ERROR: failed to parse date: " << date_str << std::endl;
1179 return -EINVAL;
1180 }
1181 }
1182
1183 ut = utime_t(epoch, nsec);
1184
1185 return 0;
1186 }
1187
1188 template <class T>
1189 static bool decode_dump(const char *field_name, bufferlist& bl, Formatter *f)
1190 {
1191 T t;
1192
1193 bufferlist::iterator iter = bl.begin();
1194
1195 try {
1196 ::decode(t, iter);
1197 } catch (buffer::error& err) {
1198 return false;
1199 }
1200
1201 encode_json(field_name, t, f);
1202
1203 return true;
1204 }
1205
1206 static bool dump_string(const char *field_name, bufferlist& bl, Formatter *f)
1207 {
1208 string val;
1209 if (bl.length() > 0) {
1210 val.assign(bl.c_str(), bl.length());
1211 }
1212 f->dump_string(field_name, val);
1213
1214 return true;
1215 }
1216
1217 void set_quota_info(RGWQuotaInfo& quota, int opt_cmd, int64_t max_size, int64_t max_objects,
1218 bool have_max_size, bool have_max_objects)
1219 {
1220 switch (opt_cmd) {
1221 case OPT_QUOTA_ENABLE:
1222 case OPT_GLOBAL_QUOTA_ENABLE:
1223 quota.enabled = true;
1224
1225 // falling through on purpose
1226
1227 case OPT_QUOTA_SET:
1228 case OPT_GLOBAL_QUOTA_SET:
1229 if (have_max_objects) {
1230 if (max_objects < 0) {
1231 quota.max_objects = -1;
1232 } else {
1233 quota.max_objects = max_objects;
1234 }
1235 }
1236 if (have_max_size) {
1237 if (max_size < 0) {
1238 quota.max_size = -1;
1239 } else {
1240 quota.max_size = rgw_rounded_kb(max_size) * 1024;
1241 }
1242 }
1243 break;
1244 case OPT_QUOTA_DISABLE:
1245 case OPT_GLOBAL_QUOTA_DISABLE:
1246 quota.enabled = false;
1247 break;
1248 }
1249 }
1250
1251 int set_bucket_quota(RGWRados *store, int opt_cmd,
1252 const string& tenant_name, const string& bucket_name,
1253 int64_t max_size, int64_t max_objects,
1254 bool have_max_size, bool have_max_objects)
1255 {
1256 RGWBucketInfo bucket_info;
1257 map<string, bufferlist> attrs;
1258 RGWObjectCtx obj_ctx(store);
1259 int r = store->get_bucket_info(obj_ctx, tenant_name, bucket_name, bucket_info, NULL, &attrs);
1260 if (r < 0) {
1261 cerr << "could not get bucket info for bucket=" << bucket_name << ": " << cpp_strerror(-r) << std::endl;
1262 return -r;
1263 }
1264
1265 set_quota_info(bucket_info.quota, opt_cmd, max_size, max_objects, have_max_size, have_max_objects);
1266
1267 r = store->put_bucket_instance_info(bucket_info, false, real_time(), &attrs);
1268 if (r < 0) {
1269 cerr << "ERROR: failed writing bucket instance info: " << cpp_strerror(-r) << std::endl;
1270 return -r;
1271 }
1272 return 0;
1273 }
1274
1275 int set_user_bucket_quota(int opt_cmd, RGWUser& user, RGWUserAdminOpState& op_state, int64_t max_size, int64_t max_objects,
1276 bool have_max_size, bool have_max_objects)
1277 {
1278 RGWUserInfo& user_info = op_state.get_user_info();
1279
1280 set_quota_info(user_info.bucket_quota, opt_cmd, max_size, max_objects, have_max_size, have_max_objects);
1281
1282 op_state.set_bucket_quota(user_info.bucket_quota);
1283
1284 string err;
1285 int r = user.modify(op_state, &err);
1286 if (r < 0) {
1287 cerr << "ERROR: failed updating user info: " << cpp_strerror(-r) << ": " << err << std::endl;
1288 return -r;
1289 }
1290 return 0;
1291 }
1292
1293 int set_user_quota(int opt_cmd, RGWUser& user, RGWUserAdminOpState& op_state, int64_t max_size, int64_t max_objects,
1294 bool have_max_size, bool have_max_objects)
1295 {
1296 RGWUserInfo& user_info = op_state.get_user_info();
1297
1298 set_quota_info(user_info.user_quota, opt_cmd, max_size, max_objects, have_max_size, have_max_objects);
1299
1300 op_state.set_user_quota(user_info.user_quota);
1301
1302 string err;
1303 int r = user.modify(op_state, &err);
1304 if (r < 0) {
1305 cerr << "ERROR: failed updating user info: " << cpp_strerror(-r) << ": " << err << std::endl;
1306 return -r;
1307 }
1308 return 0;
1309 }
1310
1311 static bool bucket_object_check_filter(const string& name)
1312 {
1313 rgw_obj_key k;
1314 string ns; /* empty namespace */
1315 return rgw_obj_key::oid_to_key_in_ns(name, &k, ns);
1316 }
1317
1318 int check_min_obj_stripe_size(RGWRados *store, RGWBucketInfo& bucket_info, rgw_obj& obj, uint64_t min_stripe_size, bool *need_rewrite)
1319 {
1320 map<string, bufferlist> attrs;
1321 uint64_t obj_size;
1322
1323 RGWObjectCtx obj_ctx(store);
1324 RGWRados::Object op_target(store, bucket_info, obj_ctx, obj);
1325 RGWRados::Object::Read read_op(&op_target);
1326
1327 read_op.params.attrs = &attrs;
1328 read_op.params.obj_size = &obj_size;
1329
1330 int ret = read_op.prepare();
1331 if (ret < 0) {
1332 lderr(store->ctx()) << "ERROR: failed to stat object, returned error: " << cpp_strerror(-ret) << dendl;
1333 return ret;
1334 }
1335
1336 map<string, bufferlist>::iterator iter;
1337 iter = attrs.find(RGW_ATTR_MANIFEST);
1338 if (iter == attrs.end()) {
1339 *need_rewrite = (obj_size >= min_stripe_size);
1340 return 0;
1341 }
1342
1343 RGWObjManifest manifest;
1344
1345 try {
1346 bufferlist& bl = iter->second;
1347 bufferlist::iterator biter = bl.begin();
1348 ::decode(manifest, biter);
1349 } catch (buffer::error& err) {
1350 ldout(store->ctx(), 0) << "ERROR: failed to decode manifest" << dendl;
1351 return -EIO;
1352 }
1353
1354 map<uint64_t, RGWObjManifestPart>& objs = manifest.get_explicit_objs();
1355 map<uint64_t, RGWObjManifestPart>::iterator oiter;
1356 for (oiter = objs.begin(); oiter != objs.end(); ++oiter) {
1357 RGWObjManifestPart& part = oiter->second;
1358
1359 if (part.size >= min_stripe_size) {
1360 *need_rewrite = true;
1361 return 0;
1362 }
1363 }
1364 *need_rewrite = false;
1365
1366 return 0;
1367 }
1368
1369
1370 int check_obj_locator_underscore(RGWBucketInfo& bucket_info, rgw_obj& obj, rgw_obj_key& key, bool fix, bool remove_bad, Formatter *f) {
1371 f->open_object_section("object");
1372 f->open_object_section("key");
1373 f->dump_string("type", "head");
1374 f->dump_string("name", key.name);
1375 f->dump_string("instance", key.instance);
1376 f->close_section();
1377
1378 string oid;
1379 string locator;
1380
1381 get_obj_bucket_and_oid_loc(obj, oid, locator);
1382
1383 f->dump_string("oid", oid);
1384 f->dump_string("locator", locator);
1385
1386
1387 RGWObjectCtx obj_ctx(store);
1388
1389 RGWRados::Object op_target(store, bucket_info, obj_ctx, obj);
1390 RGWRados::Object::Read read_op(&op_target);
1391
1392 int ret = read_op.prepare();
1393 bool needs_fixing = (ret == -ENOENT);
1394
1395 f->dump_bool("needs_fixing", needs_fixing);
1396
1397 string status = (needs_fixing ? "needs_fixing" : "ok");
1398
1399 if ((needs_fixing || remove_bad) && fix) {
1400 ret = store->fix_head_obj_locator(bucket_info, needs_fixing, remove_bad, key);
1401 if (ret < 0) {
1402 cerr << "ERROR: fix_head_object_locator() returned ret=" << ret << std::endl;
1403 goto done;
1404 }
1405 status = "fixed";
1406 }
1407
1408 done:
1409 f->dump_string("status", status);
1410
1411 f->close_section();
1412
1413 return 0;
1414 }
1415
1416 int check_obj_tail_locator_underscore(RGWBucketInfo& bucket_info, rgw_obj& obj, rgw_obj_key& key, bool fix, Formatter *f) {
1417 f->open_object_section("object");
1418 f->open_object_section("key");
1419 f->dump_string("type", "tail");
1420 f->dump_string("name", key.name);
1421 f->dump_string("instance", key.instance);
1422 f->close_section();
1423
1424 bool needs_fixing;
1425 string status;
1426
1427 int ret = store->fix_tail_obj_locator(bucket_info, key, fix, &needs_fixing);
1428 if (ret < 0) {
1429 cerr << "ERROR: fix_tail_object_locator_underscore() returned ret=" << ret << std::endl;
1430 status = "failed";
1431 } else {
1432 status = (needs_fixing && !fix ? "needs_fixing" : "ok");
1433 }
1434
1435 f->dump_bool("needs_fixing", needs_fixing);
1436 f->dump_string("status", status);
1437
1438 f->close_section();
1439
1440 return 0;
1441 }
1442
1443 int do_check_object_locator(const string& tenant_name, const string& bucket_name,
1444 bool fix, bool remove_bad, Formatter *f)
1445 {
1446 if (remove_bad && !fix) {
1447 cerr << "ERROR: can't have remove_bad specified without fix" << std::endl;
1448 return -EINVAL;
1449 }
1450
1451 RGWBucketInfo bucket_info;
1452 rgw_bucket bucket;
1453 string bucket_id;
1454
1455 f->open_object_section("bucket");
1456 f->dump_string("bucket", bucket_name);
1457 int ret = init_bucket(tenant_name, bucket_name, bucket_id, bucket_info, bucket);
1458 if (ret < 0) {
1459 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
1460 return ret;
1461 }
1462 bool truncated;
1463 int count = 0;
1464
1465 int max_entries = 1000;
1466
1467 string prefix;
1468 string delim;
1469 vector<rgw_bucket_dir_entry> result;
1470 map<string, bool> common_prefixes;
1471 string ns;
1472
1473 RGWRados::Bucket target(store, bucket_info);
1474 RGWRados::Bucket::List list_op(&target);
1475
1476 string marker;
1477
1478 list_op.params.prefix = prefix;
1479 list_op.params.delim = delim;
1480 list_op.params.marker = rgw_obj_key(marker);
1481 list_op.params.ns = ns;
1482 list_op.params.enforce_ns = true;
1483 list_op.params.list_versions = true;
1484
1485 f->open_array_section("check_objects");
1486 do {
1487 ret = list_op.list_objects(max_entries - count, &result, &common_prefixes, &truncated);
1488 if (ret < 0) {
1489 cerr << "ERROR: store->list_objects(): " << cpp_strerror(-ret) << std::endl;
1490 return -ret;
1491 }
1492
1493 count += result.size();
1494
1495 for (vector<rgw_bucket_dir_entry>::iterator iter = result.begin(); iter != result.end(); ++iter) {
1496 rgw_obj_key key = iter->key;
1497 rgw_obj obj(bucket, key);
1498
1499 if (key.name[0] == '_') {
1500 ret = check_obj_locator_underscore(bucket_info, obj, key, fix, remove_bad, f);
1501
1502 if (ret >= 0) {
1503 ret = check_obj_tail_locator_underscore(bucket_info, obj, key, fix, f);
1504 }
1505 }
1506 }
1507 f->flush(cout);
1508 } while (truncated && count < max_entries);
1509 f->close_section();
1510 f->close_section();
1511
1512 f->flush(cout);
1513
1514 return 0;
1515 }
1516
1517 /// search for a matching zone/zonegroup id and return a connection if found
1518 static boost::optional<RGWRESTConn> get_remote_conn(RGWRados *store,
1519 const RGWZoneGroup& zonegroup,
1520 const std::string& remote)
1521 {
1522 boost::optional<RGWRESTConn> conn;
1523 if (remote == zonegroup.get_id()) {
1524 conn.emplace(store->ctx(), store, remote, zonegroup.endpoints);
1525 } else {
1526 for (const auto& z : zonegroup.zones) {
1527 const auto& zone = z.second;
1528 if (remote == zone.id) {
1529 conn.emplace(store->ctx(), store, remote, zone.endpoints);
1530 break;
1531 }
1532 }
1533 }
1534 return conn;
1535 }
1536
1537 /// search each zonegroup for a connection
1538 static boost::optional<RGWRESTConn> get_remote_conn(RGWRados *store,
1539 const RGWPeriodMap& period_map,
1540 const std::string& remote)
1541 {
1542 boost::optional<RGWRESTConn> conn;
1543 for (const auto& zg : period_map.zonegroups) {
1544 conn = get_remote_conn(store, zg.second, remote);
1545 if (conn) {
1546 break;
1547 }
1548 }
1549 return conn;
1550 }
1551
1552 #define MAX_REST_RESPONSE (128 * 1024) // we expect a very small response
1553 static int send_to_remote_gateway(RGWRESTConn* conn, req_info& info,
1554 bufferlist& in_data, JSONParser& parser)
1555 {
1556 bufferlist response;
1557 rgw_user user;
1558 int ret = conn->forward(user, info, NULL, MAX_REST_RESPONSE, &in_data, &response);
1559
1560 int parse_ret = parser.parse(response.c_str(), response.length());
1561 if (parse_ret < 0) {
1562 cerr << "failed to parse response" << std::endl;
1563 return parse_ret;
1564 }
1565 return ret;
1566 }
1567
1568 static int send_to_url(const string& url, const string& access,
1569 const string& secret, req_info& info,
1570 bufferlist& in_data, JSONParser& parser)
1571 {
1572 if (access.empty() || secret.empty()) {
1573 cerr << "An --access-key and --secret must be provided with --url." << std::endl;
1574 return -EINVAL;
1575 }
1576 RGWAccessKey key;
1577 key.id = access;
1578 key.key = secret;
1579
1580 param_vec_t params;
1581 RGWRESTSimpleRequest req(g_ceph_context, url, NULL, &params);
1582
1583 bufferlist response;
1584 int ret = req.forward_request(key, info, MAX_REST_RESPONSE, &in_data, &response);
1585
1586 int parse_ret = parser.parse(response.c_str(), response.length());
1587 if (parse_ret < 0) {
1588 cout << "failed to parse response" << std::endl;
1589 return parse_ret;
1590 }
1591 return ret;
1592 }
1593
1594 static int send_to_remote_or_url(RGWRESTConn *conn, const string& url,
1595 const string& access, const string& secret,
1596 req_info& info, bufferlist& in_data,
1597 JSONParser& parser)
1598 {
1599 if (url.empty()) {
1600 return send_to_remote_gateway(conn, info, in_data, parser);
1601 }
1602 return send_to_url(url, access, secret, info, in_data, parser);
1603 }
1604
1605 static int commit_period(RGWRealm& realm, RGWPeriod& period,
1606 string remote, const string& url,
1607 const string& access, const string& secret,
1608 bool force)
1609 {
1610 const string& master_zone = period.get_master_zone();
1611 if (master_zone.empty()) {
1612 cerr << "cannot commit period: period does not have a master zone of a master zonegroup" << std::endl;
1613 return -EINVAL;
1614 }
1615 // are we the period's master zone?
1616 if (store->get_zone_params().get_id() == master_zone) {
1617 // read the current period
1618 RGWPeriod current_period;
1619 int ret = current_period.init(g_ceph_context, store, realm.get_id());
1620 if (ret < 0) {
1621 cerr << "Error initializing current period: "
1622 << cpp_strerror(-ret) << std::endl;
1623 return ret;
1624 }
1625 // the master zone can commit locally
1626 ret = period.commit(realm, current_period, cerr, force);
1627 if (ret < 0) {
1628 cerr << "failed to commit period: " << cpp_strerror(-ret) << std::endl;
1629 }
1630 return ret;
1631 }
1632
1633 if (remote.empty() && url.empty()) {
1634 // use the new master zone's connection
1635 remote = master_zone;
1636 cout << "Sending period to new master zone " << remote << std::endl;
1637 }
1638 boost::optional<RGWRESTConn> conn;
1639 RGWRESTConn *remote_conn = nullptr;
1640 if (!remote.empty()) {
1641 conn = get_remote_conn(store, period.get_map(), remote);
1642 if (!conn) {
1643 cerr << "failed to find a zone or zonegroup for remote "
1644 << remote << std::endl;
1645 return -ENOENT;
1646 }
1647 remote_conn = &*conn;
1648 }
1649
1650 // push period to the master with an empty period id
1651 period.set_id("");
1652
1653 RGWEnv env;
1654 req_info info(g_ceph_context, &env);
1655 info.method = "POST";
1656 info.request_uri = "/admin/realm/period";
1657
1658 // json format into a bufferlist
1659 JSONFormatter jf(false);
1660 encode_json("period", period, &jf);
1661 bufferlist bl;
1662 jf.flush(bl);
1663
1664 JSONParser p;
1665 int ret = send_to_remote_or_url(remote_conn, url, access, secret, info, bl, p);
1666 if (ret < 0) {
1667 cerr << "request failed: " << cpp_strerror(-ret) << std::endl;
1668
1669 // did we parse an error message?
1670 auto message = p.find_obj("Message");
1671 if (message) {
1672 cerr << "Reason: " << message->get_data() << std::endl;
1673 }
1674 return ret;
1675 }
1676
1677 // decode the response and store it back
1678 try {
1679 decode_json_obj(period, &p);
1680 } catch (JSONDecoder::err& e) {
1681 cout << "failed to decode JSON input: " << e.message << std::endl;
1682 return -EINVAL;
1683 }
1684 if (period.get_id().empty()) {
1685 cerr << "Period commit got back an empty period id" << std::endl;
1686 return -EINVAL;
1687 }
1688 // the master zone gave us back the period that it committed, so it's
1689 // safe to save it as our latest epoch
1690 ret = period.store_info(false);
1691 if (ret < 0) {
1692 cerr << "Error storing committed period " << period.get_id() << ": "
1693 << cpp_strerror(ret) << std::endl;
1694 return ret;
1695 }
1696 ret = period.set_latest_epoch(period.get_epoch());
1697 if (ret < 0) {
1698 cerr << "Error updating period epoch: " << cpp_strerror(ret) << std::endl;
1699 return ret;
1700 }
1701 ret = period.reflect();
1702 if (ret < 0) {
1703 cerr << "Error updating local objects: " << cpp_strerror(ret) << std::endl;
1704 return ret;
1705 }
1706 realm.notify_new_period(period);
1707 return ret;
1708 }
1709
1710 static int update_period(const string& realm_id, const string& realm_name,
1711 const string& period_id, const string& period_epoch,
1712 bool commit, const string& remote, const string& url,
1713 const string& access, const string& secret,
1714 Formatter *formatter, bool force)
1715 {
1716 RGWRealm realm(realm_id, realm_name);
1717 int ret = realm.init(g_ceph_context, store);
1718 if (ret < 0 ) {
1719 cerr << "Error initializing realm " << cpp_strerror(-ret) << std::endl;
1720 return ret;
1721 }
1722 epoch_t epoch = 0;
1723 if (!period_epoch.empty()) {
1724 epoch = atoi(period_epoch.c_str());
1725 }
1726 RGWPeriod period(period_id, epoch);
1727 ret = period.init(g_ceph_context, store, realm.get_id());
1728 if (ret < 0) {
1729 cerr << "period init failed: " << cpp_strerror(-ret) << std::endl;
1730 return ret;
1731 }
1732 period.fork();
1733 ret = period.update();
1734 if(ret < 0) {
1735 // Dropping the error message here, as both the ret codes were handled in
1736 // period.update()
1737 return ret;
1738 }
1739 ret = period.store_info(false);
1740 if (ret < 0) {
1741 cerr << "failed to store period: " << cpp_strerror(-ret) << std::endl;
1742 return ret;
1743 }
1744 if (commit) {
1745 ret = commit_period(realm, period, remote, url, access, secret, force);
1746 if (ret < 0) {
1747 cerr << "failed to commit period: " << cpp_strerror(-ret) << std::endl;
1748 return ret;
1749 }
1750 }
1751 encode_json("period", period, formatter);
1752 formatter->flush(cout);
1753 cout << std::endl;
1754 return 0;
1755 }
1756
1757 static int init_bucket_for_sync(const string& tenant, const string& bucket_name,
1758 const string& bucket_id, rgw_bucket& bucket)
1759 {
1760 RGWBucketInfo bucket_info;
1761
1762 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
1763 if (ret < 0) {
1764 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
1765 return ret;
1766 }
1767
1768 return 0;
1769 }
1770
1771 static int do_period_pull(RGWRESTConn *remote_conn, const string& url,
1772 const string& access_key, const string& secret_key,
1773 const string& realm_id, const string& realm_name,
1774 const string& period_id, const string& period_epoch,
1775 RGWPeriod *period)
1776 {
1777 RGWEnv env;
1778 req_info info(g_ceph_context, &env);
1779 info.method = "GET";
1780 info.request_uri = "/admin/realm/period";
1781
1782 map<string, string> &params = info.args.get_params();
1783 if (!realm_id.empty())
1784 params["realm_id"] = realm_id;
1785 if (!realm_name.empty())
1786 params["realm_name"] = realm_name;
1787 if (!period_id.empty())
1788 params["period_id"] = period_id;
1789 if (!period_epoch.empty())
1790 params["epoch"] = period_epoch;
1791
1792 bufferlist bl;
1793 JSONParser p;
1794 int ret = send_to_remote_or_url(remote_conn, url, access_key, secret_key,
1795 info, bl, p);
1796 if (ret < 0) {
1797 cerr << "request failed: " << cpp_strerror(-ret) << std::endl;
1798 return ret;
1799 }
1800 ret = period->init(g_ceph_context, store, false);
1801 if (ret < 0) {
1802 cerr << "faile to init period " << cpp_strerror(-ret) << std::endl;
1803 return ret;
1804 }
1805 try {
1806 decode_json_obj(*period, &p);
1807 } catch (JSONDecoder::err& e) {
1808 cout << "failed to decode JSON input: " << e.message << std::endl;
1809 return -EINVAL;
1810 }
1811 ret = period->store_info(false);
1812 if (ret < 0) {
1813 cerr << "Error storing period " << period->get_id() << ": " << cpp_strerror(ret) << std::endl;
1814 }
1815
1816 return 0;
1817 }
1818
1819 static int read_current_period_id(RGWRados* store, const std::string& realm_id,
1820 const std::string& realm_name,
1821 std::string* period_id)
1822 {
1823 RGWRealm realm(realm_id, realm_name);
1824 int ret = realm.init(g_ceph_context, store);
1825 if (ret < 0) {
1826 std::cerr << "failed to read realm: " << cpp_strerror(-ret) << std::endl;
1827 return ret;
1828 }
1829 *period_id = realm.get_current_period();
1830 return 0;
1831 }
1832
1833 void flush_ss(stringstream& ss, list<string>& l)
1834 {
1835 if (!ss.str().empty()) {
1836 l.push_back(ss.str());
1837 }
1838 ss.str("");
1839 }
1840
1841 stringstream& push_ss(stringstream& ss, list<string>& l, int tab = 0)
1842 {
1843 flush_ss(ss, l);
1844 if (tab > 0) {
1845 ss << setw(tab) << "" << setw(1);
1846 }
1847 return ss;
1848 }
1849
1850 static void get_md_sync_status(list<string>& status)
1851 {
1852 RGWMetaSyncStatusManager sync(store, store->get_async_rados());
1853
1854 int ret = sync.init();
1855 if (ret < 0) {
1856 status.push_back(string("failed to retrieve sync info: sync.init() failed: ") + cpp_strerror(-ret));
1857 return;
1858 }
1859
1860 rgw_meta_sync_status sync_status;
1861 ret = sync.read_sync_status(&sync_status);
1862 if (ret < 0) {
1863 status.push_back(string("failed to read sync status: ") + cpp_strerror(-ret));
1864 return;
1865 }
1866
1867 string status_str;
1868 switch (sync_status.sync_info.state) {
1869 case rgw_meta_sync_info::StateInit:
1870 status_str = "init";
1871 break;
1872 case rgw_meta_sync_info::StateBuildingFullSyncMaps:
1873 status_str = "preparing for full sync";
1874 break;
1875 case rgw_meta_sync_info::StateSync:
1876 status_str = "syncing";
1877 break;
1878 default:
1879 status_str = "unknown";
1880 }
1881
1882 status.push_back(status_str);
1883
1884 uint64_t full_total = 0;
1885 uint64_t full_complete = 0;
1886
1887 int num_full = 0;
1888 int num_inc = 0;
1889 int total_shards = 0;
1890
1891 for (auto marker_iter : sync_status.sync_markers) {
1892 full_total += marker_iter.second.total_entries;
1893 total_shards++;
1894 if (marker_iter.second.state == rgw_meta_sync_marker::SyncState::FullSync) {
1895 num_full++;
1896 full_complete += marker_iter.second.pos;
1897 } else {
1898 full_complete += marker_iter.second.total_entries;
1899 }
1900 if (marker_iter.second.state == rgw_meta_sync_marker::SyncState::IncrementalSync) {
1901 num_inc++;
1902 }
1903 }
1904
1905 stringstream ss;
1906 push_ss(ss, status) << "full sync: " << num_full << "/" << total_shards << " shards";
1907
1908 if (num_full > 0) {
1909 push_ss(ss, status) << "full sync: " << full_total - full_complete << " entries to sync";
1910 }
1911
1912 push_ss(ss, status) << "incremental sync: " << num_inc << "/" << total_shards << " shards";
1913
1914 rgw_mdlog_info log_info;
1915 ret = sync.read_log_info(&log_info);
1916 if (ret < 0) {
1917 status.push_back(string("failed to fetch local sync status: ") + cpp_strerror(-ret));
1918 return;
1919 }
1920
1921 map<int, RGWMetadataLogInfo> master_shards_info;
1922 string master_period = store->get_current_period_id();
1923
1924 ret = sync.read_master_log_shards_info(master_period, &master_shards_info);
1925 if (ret < 0) {
1926 status.push_back(string("failed to fetch master sync status: ") + cpp_strerror(-ret));
1927 return;
1928 }
1929
1930 map<int, string> shards_behind;
1931 if (sync_status.sync_info.period != master_period) {
1932 status.push_back(string("master is on a different period: master_period=" +
1933 master_period + " local_period=" + sync_status.sync_info.period));
1934 } else {
1935 for (auto local_iter : sync_status.sync_markers) {
1936 int shard_id = local_iter.first;
1937 auto iter = master_shards_info.find(shard_id);
1938
1939 if (iter == master_shards_info.end()) {
1940 /* huh? */
1941 derr << "ERROR: could not find remote sync shard status for shard_id=" << shard_id << dendl;
1942 continue;
1943 }
1944 auto master_marker = iter->second.marker;
1945 if (local_iter.second.state == rgw_meta_sync_marker::SyncState::IncrementalSync &&
1946 master_marker > local_iter.second.marker) {
1947 shards_behind[shard_id] = local_iter.second.marker;
1948 }
1949 }
1950 }
1951
1952 int total_behind = shards_behind.size() + (sync_status.sync_info.num_shards - num_inc);
1953 if (total_behind == 0) {
1954 push_ss(ss, status) << "metadata is caught up with master";
1955 } else {
1956 push_ss(ss, status) << "metadata is behind on " << total_behind << " shards";
1957
1958 map<int, rgw_mdlog_shard_data> master_pos;
1959 ret = sync.read_master_log_shards_next(sync_status.sync_info.period, shards_behind, &master_pos);
1960 if (ret < 0) {
1961 derr << "ERROR: failed to fetch master next positions (" << cpp_strerror(-ret) << ")" << dendl;
1962 } else {
1963 ceph::real_time oldest;
1964 for (auto iter : master_pos) {
1965 rgw_mdlog_shard_data& shard_data = iter.second;
1966
1967 if (!shard_data.entries.empty()) {
1968 rgw_mdlog_entry& entry = shard_data.entries.front();
1969 if (ceph::real_clock::is_zero(oldest)) {
1970 oldest = entry.timestamp;
1971 } else if (!ceph::real_clock::is_zero(entry.timestamp) && entry.timestamp < oldest) {
1972 oldest = entry.timestamp;
1973 }
1974 }
1975 }
1976
1977 if (!ceph::real_clock::is_zero(oldest)) {
1978 push_ss(ss, status) << "oldest incremental change not applied: " << oldest;
1979 }
1980 }
1981 }
1982
1983 flush_ss(ss, status);
1984 }
1985
1986 static void get_data_sync_status(const string& source_zone, list<string>& status, int tab)
1987 {
1988 stringstream ss;
1989
1990 auto ziter = store->zone_by_id.find(source_zone);
1991 if (ziter == store->zone_by_id.end()) {
1992 push_ss(ss, status, tab) << string("zone not found");
1993 flush_ss(ss, status);
1994 return;
1995 }
1996 RGWZone& sz = ziter->second;
1997
1998 if (!store->zone_syncs_from(store->get_zone(), sz)) {
1999 push_ss(ss, status, tab) << string("not syncing from zone");
2000 flush_ss(ss, status);
2001 return;
2002 }
2003 RGWDataSyncStatusManager sync(store, store->get_async_rados(), source_zone);
2004
2005 int ret = sync.init();
2006 if (ret < 0) {
2007 push_ss(ss, status, tab) << string("failed to retrieve sync info: ") + cpp_strerror(-ret);
2008 flush_ss(ss, status);
2009 return;
2010 }
2011
2012 rgw_data_sync_status sync_status;
2013 ret = sync.read_sync_status(&sync_status);
2014 if (ret < 0 && ret != -ENOENT) {
2015 push_ss(ss, status, tab) << string("failed read sync status: ") + cpp_strerror(-ret);
2016 return;
2017 }
2018
2019 string status_str;
2020 switch (sync_status.sync_info.state) {
2021 case rgw_data_sync_info::StateInit:
2022 status_str = "init";
2023 break;
2024 case rgw_data_sync_info::StateBuildingFullSyncMaps:
2025 status_str = "preparing for full sync";
2026 break;
2027 case rgw_data_sync_info::StateSync:
2028 status_str = "syncing";
2029 break;
2030 default:
2031 status_str = "unknown";
2032 }
2033
2034 push_ss(ss, status, tab) << status_str;
2035
2036 uint64_t full_total = 0;
2037 uint64_t full_complete = 0;
2038
2039 int num_full = 0;
2040 int num_inc = 0;
2041 int total_shards = 0;
2042
2043 for (auto marker_iter : sync_status.sync_markers) {
2044 full_total += marker_iter.second.total_entries;
2045 total_shards++;
2046 if (marker_iter.second.state == rgw_data_sync_marker::SyncState::FullSync) {
2047 num_full++;
2048 full_complete += marker_iter.second.pos;
2049 } else {
2050 full_complete += marker_iter.second.total_entries;
2051 }
2052 if (marker_iter.second.state == rgw_data_sync_marker::SyncState::IncrementalSync) {
2053 num_inc++;
2054 }
2055 }
2056
2057 push_ss(ss, status, tab) << "full sync: " << num_full << "/" << total_shards << " shards";
2058
2059 if (num_full > 0) {
2060 push_ss(ss, status, tab) << "full sync: " << full_total - full_complete << " buckets to sync";
2061 }
2062
2063 push_ss(ss, status, tab) << "incremental sync: " << num_inc << "/" << total_shards << " shards";
2064
2065 rgw_datalog_info log_info;
2066 ret = sync.read_log_info(&log_info);
2067 if (ret < 0) {
2068 push_ss(ss, status, tab) << string("failed to fetch local sync status: ") + cpp_strerror(-ret);
2069 return;
2070 }
2071
2072
2073 map<int, RGWDataChangesLogInfo> source_shards_info;
2074
2075 ret = sync.read_source_log_shards_info(&source_shards_info);
2076 if (ret < 0) {
2077 push_ss(ss, status, tab) << string("failed to fetch source sync status: ") + cpp_strerror(-ret);
2078 return;
2079 }
2080
2081 map<int, string> shards_behind;
2082
2083 for (auto local_iter : sync_status.sync_markers) {
2084 int shard_id = local_iter.first;
2085 auto iter = source_shards_info.find(shard_id);
2086
2087 if (iter == source_shards_info.end()) {
2088 /* huh? */
2089 derr << "ERROR: could not find remote sync shard status for shard_id=" << shard_id << dendl;
2090 continue;
2091 }
2092 auto master_marker = iter->second.marker;
2093 if (local_iter.second.state == rgw_data_sync_marker::SyncState::IncrementalSync &&
2094 master_marker > local_iter.second.marker) {
2095 shards_behind[shard_id] = local_iter.second.marker;
2096 }
2097 }
2098
2099 int total_behind = shards_behind.size() + (sync_status.sync_info.num_shards - num_inc);
2100 if (total_behind == 0) {
2101 push_ss(ss, status, tab) << "data is caught up with source";
2102 } else {
2103 push_ss(ss, status, tab) << "data is behind on " << total_behind << " shards";
2104
2105 map<int, rgw_datalog_shard_data> master_pos;
2106 ret = sync.read_source_log_shards_next(shards_behind, &master_pos);
2107 if (ret < 0) {
2108 derr << "ERROR: failed to fetch next positions (" << cpp_strerror(-ret) << ")" << dendl;
2109 } else {
2110 ceph::real_time oldest;
2111 for (auto iter : master_pos) {
2112 rgw_datalog_shard_data& shard_data = iter.second;
2113
2114 if (!shard_data.entries.empty()) {
2115 rgw_datalog_entry& entry = shard_data.entries.front();
2116 if (ceph::real_clock::is_zero(oldest)) {
2117 oldest = entry.timestamp;
2118 } else if (!ceph::real_clock::is_zero(entry.timestamp) && entry.timestamp < oldest) {
2119 oldest = entry.timestamp;
2120 }
2121 }
2122 }
2123
2124 if (!ceph::real_clock::is_zero(oldest)) {
2125 push_ss(ss, status, tab) << "oldest incremental change not applied: " << oldest;
2126 }
2127 }
2128 }
2129
2130 flush_ss(ss, status);
2131 }
2132
2133 static void tab_dump(const string& header, int width, const list<string>& entries)
2134 {
2135 string s = header;
2136
2137 for (auto e : entries) {
2138 cout << std::setw(width) << s << std::setw(1) << " " << e << std::endl;
2139 s.clear();
2140 }
2141 }
2142
2143
2144 static void sync_status(Formatter *formatter)
2145 {
2146 RGWRealm& realm = store->realm;
2147 RGWZoneGroup& zonegroup = store->get_zonegroup();
2148 RGWZone& zone = store->get_zone();
2149
2150 int width = 15;
2151
2152 cout << std::setw(width) << "realm" << std::setw(1) << " " << realm.get_id() << " (" << realm.get_name() << ")" << std::endl;
2153 cout << std::setw(width) << "zonegroup" << std::setw(1) << " " << zonegroup.get_id() << " (" << zonegroup.get_name() << ")" << std::endl;
2154 cout << std::setw(width) << "zone" << std::setw(1) << " " << zone.id << " (" << zone.name << ")" << std::endl;
2155
2156 list<string> md_status;
2157
2158 if (store->is_meta_master()) {
2159 md_status.push_back("no sync (zone is master)");
2160 } else {
2161 get_md_sync_status(md_status);
2162 }
2163
2164 tab_dump("metadata sync", width, md_status);
2165
2166 list<string> data_status;
2167
2168 for (auto iter : store->zone_conn_map) {
2169 const string& source_id = iter.first;
2170 string zone_name;
2171 string source_str = "source: ";
2172 string s = source_str + source_id;
2173 auto siter = store->zone_by_id.find(source_id);
2174 if (siter != store->zone_by_id.end()) {
2175 s += string(" (") + siter->second.name + ")";
2176 }
2177 data_status.push_back(s);
2178 get_data_sync_status(source_id, data_status, source_str.size());
2179 }
2180
2181 tab_dump("data sync", width, data_status);
2182 }
2183
2184 static void parse_tier_config_param(const string& s, map<string, string>& out)
2185 {
2186 list<string> confs;
2187 get_str_list(s, ",", confs);
2188 for (auto c : confs) {
2189 ssize_t pos = c.find("=");
2190 if (pos < 0) {
2191 out[c] = "";
2192 } else {
2193 out[c.substr(0, pos)] = c.substr(pos + 1);
2194 }
2195 }
2196 }
2197
2198 #define RESHARD_SHARD_WINDOW 64
2199 #define RESHARD_MAX_AIO 128
2200
2201 class BucketReshardShard {
2202 RGWRados *store;
2203 RGWBucketInfo& bucket_info;
2204 int num_shard;
2205 RGWRados::BucketShard bs;
2206 vector<rgw_cls_bi_entry> entries;
2207 map<uint8_t, rgw_bucket_category_stats> stats;
2208 deque<librados::AioCompletion *>& aio_completions;
2209
2210 int wait_next_completion() {
2211 librados::AioCompletion *c = aio_completions.front();
2212 aio_completions.pop_front();
2213
2214 c->wait_for_safe();
2215
2216 int ret = c->get_return_value();
2217 c->release();
2218
2219 if (ret < 0) {
2220 cerr << "ERROR: reshard rados operation failed: " << cpp_strerror(-ret) << std::endl;
2221 return ret;
2222 }
2223
2224 return 0;
2225 }
2226
2227 int get_completion(librados::AioCompletion **c) {
2228 if (aio_completions.size() >= RESHARD_MAX_AIO) {
2229 int ret = wait_next_completion();
2230 if (ret < 0) {
2231 return ret;
2232 }
2233 }
2234
2235 *c = librados::Rados::aio_create_completion(nullptr, nullptr, nullptr);
2236 aio_completions.push_back(*c);
2237
2238 return 0;
2239 }
2240
2241 public:
2242 BucketReshardShard(RGWRados *_store, RGWBucketInfo& _bucket_info,
2243 int _num_shard,
2244 deque<librados::AioCompletion *>& _completions) : store(_store), bucket_info(_bucket_info), bs(store),
2245 aio_completions(_completions) {
2246 num_shard = (bucket_info.num_shards > 0 ? _num_shard : -1);
2247 bs.init(bucket_info.bucket, num_shard);
2248 }
2249
2250 int get_num_shard() {
2251 return num_shard;
2252 }
2253
2254 int add_entry(rgw_cls_bi_entry& entry, bool account, uint8_t category,
2255 const rgw_bucket_category_stats& entry_stats) {
2256 entries.push_back(entry);
2257 if (account) {
2258 rgw_bucket_category_stats& target = stats[category];
2259 target.num_entries += entry_stats.num_entries;
2260 target.total_size += entry_stats.total_size;
2261 target.total_size_rounded += entry_stats.total_size_rounded;
2262 }
2263 if (entries.size() >= RESHARD_SHARD_WINDOW) {
2264 int ret = flush();
2265 if (ret < 0) {
2266 return ret;
2267 }
2268 }
2269 return 0;
2270 }
2271 int flush() {
2272 if (entries.size() == 0) {
2273 return 0;
2274 }
2275
2276 librados::ObjectWriteOperation op;
2277 for (auto& entry : entries) {
2278 store->bi_put(op, bs, entry);
2279 }
2280 cls_rgw_bucket_update_stats(op, false, stats);
2281
2282 librados::AioCompletion *c;
2283 int ret = get_completion(&c);
2284 if (ret < 0) {
2285 return ret;
2286 }
2287 ret = bs.index_ctx.aio_operate(bs.bucket_obj, c, &op);
2288 if (ret < 0) {
2289 std::cerr << "ERROR: failed to store entries in target bucket shard (bs=" << bs.bucket << "/" << bs.shard_id << ") error=" << cpp_strerror(-ret) << std::endl;
2290 return ret;
2291 }
2292 entries.clear();
2293 stats.clear();
2294 return 0;
2295 }
2296
2297 int wait_all_aio() {
2298 int ret = 0;
2299 while (!aio_completions.empty()) {
2300 int r = wait_next_completion();
2301 if (r < 0) {
2302 ret = r;
2303 }
2304 }
2305 return ret;
2306 }
2307 };
2308
2309 class BucketReshardManager {
2310 RGWRados *store;
2311 RGWBucketInfo& target_bucket_info;
2312 deque<librados::AioCompletion *> completions;
2313 int num_target_shards;
2314 vector<BucketReshardShard *> target_shards;
2315
2316 public:
2317 BucketReshardManager(RGWRados *_store, RGWBucketInfo& _target_bucket_info, int _num_target_shards) : store(_store), target_bucket_info(_target_bucket_info),
2318 num_target_shards(_num_target_shards) {
2319 target_shards.resize(num_target_shards);
2320 for (int i = 0; i < num_target_shards; ++i) {
2321 target_shards[i] = new BucketReshardShard(store, target_bucket_info, i, completions);
2322 }
2323 }
2324
2325 ~BucketReshardManager() {
2326 for (auto& shard : target_shards) {
2327 int ret = shard->wait_all_aio();
2328 if (ret < 0) {
2329 ldout(store->ctx(), 20) << __func__ << ": shard->wait_all_aio() returned ret=" << ret << dendl;
2330 }
2331 }
2332 }
2333
2334 int add_entry(int shard_index,
2335 rgw_cls_bi_entry& entry, bool account, uint8_t category,
2336 const rgw_bucket_category_stats& entry_stats) {
2337 int ret = target_shards[shard_index]->add_entry(entry, account, category, entry_stats);
2338 if (ret < 0) {
2339 cerr << "ERROR: target_shards.add_entry(" << entry.idx << ") returned error: " << cpp_strerror(-ret) << std::endl;
2340 return ret;
2341 }
2342 return 0;
2343 }
2344
2345 int finish() {
2346 int ret = 0;
2347 for (auto& shard : target_shards) {
2348 int r = shard->flush();
2349 if (r < 0) {
2350 cerr << "ERROR: target_shards[" << shard->get_num_shard() << "].flush() returned error: " << cpp_strerror(-r) << std::endl;
2351 ret = r;
2352 }
2353 }
2354 for (auto& shard : target_shards) {
2355 int r = shard->wait_all_aio();
2356 if (r < 0) {
2357 cerr << "ERROR: target_shards[" << shard->get_num_shard() << "].wait_all_aio() returned error: " << cpp_strerror(-r) << std::endl;
2358 ret = r;
2359 }
2360 delete shard;
2361 }
2362 target_shards.clear();
2363 return ret;
2364 }
2365 };
2366
2367 #ifdef BUILDING_FOR_EMBEDDED
2368 extern "C" int cephd_rgw_admin(int argc, const char **argv)
2369 #else
2370 int main(int argc, const char **argv)
2371 #endif
2372 {
2373 vector<const char*> args;
2374 argv_to_vec(argc, (const char **)argv, args);
2375 env_to_vec(args);
2376
2377 auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT,
2378 CODE_ENVIRONMENT_UTILITY, 0);
2379
2380 // for region -> zonegroup conversion (must happen before common_init_finish())
2381 if (!g_conf->rgw_region.empty() && g_conf->rgw_zonegroup.empty()) {
2382 g_conf->set_val_or_die("rgw_zonegroup", g_conf->rgw_region.c_str());
2383 }
2384
2385 common_init_finish(g_ceph_context);
2386
2387 rgw_user user_id;
2388 string tenant;
2389 std::string access_key, secret_key, user_email, display_name;
2390 std::string bucket_name, pool_name, object;
2391 rgw_pool pool;
2392 std::string date, subuser, access, format;
2393 std::string start_date, end_date;
2394 std::string key_type_str;
2395 std::string period_id, period_epoch, remote, url;
2396 std::string master_zonegroup, master_zone;
2397 std::string realm_name, realm_id, realm_new_name;
2398 std::string zone_name, zone_id, zone_new_name;
2399 std::string zonegroup_name, zonegroup_id, zonegroup_new_name;
2400 std::string api_name;
2401 std::string role_name, path, assume_role_doc, policy_name, perm_policy_doc, path_prefix;
2402 list<string> endpoints;
2403 int tmp_int;
2404 int sync_from_all_specified = false;
2405 bool sync_from_all = false;
2406 list<string> sync_from;
2407 list<string> sync_from_rm;
2408 std::string master_url;
2409 int is_master_int;
2410 int set_default = 0;
2411 bool is_master = false;
2412 bool is_master_set = false;
2413 int read_only_int;
2414 bool read_only = false;
2415 int is_read_only_set = false;
2416 int commit = false;
2417 int staging = false;
2418 int key_type = KEY_TYPE_UNDEFINED;
2419 rgw_bucket bucket;
2420 uint32_t perm_mask = 0;
2421 RGWUserInfo info;
2422 int opt_cmd = OPT_NO_CMD;
2423 bool need_more;
2424 int gen_access_key = 0;
2425 int gen_secret_key = 0;
2426 bool set_perm = false;
2427 bool set_temp_url_key = false;
2428 map<int, string> temp_url_keys;
2429 string bucket_id;
2430 Formatter *formatter = NULL;
2431 int purge_data = false;
2432 RGWBucketInfo bucket_info;
2433 int pretty_format = false;
2434 int show_log_entries = true;
2435 int show_log_sum = true;
2436 int skip_zero_entries = false; // log show
2437 int purge_keys = false;
2438 int yes_i_really_mean_it = false;
2439 int delete_child_objects = false;
2440 int fix = false;
2441 int remove_bad = false;
2442 int check_head_obj_locator = false;
2443 int max_buckets = -1;
2444 bool max_buckets_specified = false;
2445 map<string, bool> categories;
2446 string caps;
2447 int check_objects = false;
2448 RGWUserAdminOpState user_op;
2449 RGWBucketAdminOpState bucket_op;
2450 string infile;
2451 string metadata_key;
2452 RGWObjVersionTracker objv_tracker;
2453 string marker;
2454 string start_marker;
2455 string end_marker;
2456 int max_entries = -1;
2457 int admin = false;
2458 bool admin_specified = false;
2459 int system = false;
2460 bool system_specified = false;
2461 int shard_id = -1;
2462 bool specified_shard_id = false;
2463 string daemon_id;
2464 bool specified_daemon_id = false;
2465 string client_id;
2466 string op_id;
2467 string state_str;
2468 string replica_log_type_str;
2469 ReplicaLogType replica_log_type = ReplicaLog_Invalid;
2470 string op_mask_str;
2471 string quota_scope;
2472 string object_version;
2473 string placement_id;
2474 list<string> tags;
2475 list<string> tags_add;
2476 list<string> tags_rm;
2477
2478 int64_t max_objects = -1;
2479 int64_t max_size = -1;
2480 bool have_max_objects = false;
2481 bool have_max_size = false;
2482 int include_all = false;
2483
2484 int sync_stats = false;
2485 int bypass_gc = false;
2486 int warnings_only = false;
2487 int inconsistent_index = false;
2488
2489 int verbose = false;
2490
2491 int extra_info = false;
2492
2493 uint64_t min_rewrite_size = 4 * 1024 * 1024;
2494 uint64_t max_rewrite_size = ULLONG_MAX;
2495 uint64_t min_rewrite_stripe_size = 0;
2496
2497 BIIndexType bi_index_type = PlainIdx;
2498
2499 string job_id;
2500 int num_shards = 0;
2501 bool num_shards_specified = false;
2502 int max_concurrent_ios = 32;
2503 uint64_t orphan_stale_secs = (24 * 3600);
2504
2505 std::string val;
2506 std::ostringstream errs;
2507 string err;
2508 long long tmp = 0;
2509
2510 string source_zone_name;
2511 string source_zone; /* zone id */
2512
2513 string tier_type;
2514 bool tier_type_specified = false;
2515
2516 map<string, string> tier_config_add;
2517 map<string, string> tier_config_rm;
2518
2519 boost::optional<string> index_pool;
2520 boost::optional<string> data_pool;
2521 boost::optional<string> data_extra_pool;
2522 RGWBucketIndexType placement_index_type = RGWBIType_Normal;
2523 bool index_type_specified = false;
2524
2525 boost::optional<std::string> compression_type;
2526
2527 for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) {
2528 if (ceph_argparse_double_dash(args, i)) {
2529 break;
2530 } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) {
2531 usage();
2532 return 0;
2533 } else if (ceph_argparse_witharg(args, i, &val, "-i", "--uid", (char*)NULL)) {
2534 user_id.from_str(val);
2535 } else if (ceph_argparse_witharg(args, i, &val, "--tenant", (char*)NULL)) {
2536 tenant = val;
2537 } else if (ceph_argparse_witharg(args, i, &val, "--access-key", (char*)NULL)) {
2538 access_key = val;
2539 } else if (ceph_argparse_witharg(args, i, &val, "--subuser", (char*)NULL)) {
2540 subuser = val;
2541 } else if (ceph_argparse_witharg(args, i, &val, "--secret", "--secret-key", (char*)NULL)) {
2542 secret_key = val;
2543 } else if (ceph_argparse_witharg(args, i, &val, "-e", "--email", (char*)NULL)) {
2544 user_email = val;
2545 user_op.user_email_specified=true;
2546 } else if (ceph_argparse_witharg(args, i, &val, "-n", "--display-name", (char*)NULL)) {
2547 display_name = val;
2548 } else if (ceph_argparse_witharg(args, i, &val, "-b", "--bucket", (char*)NULL)) {
2549 bucket_name = val;
2550 } else if (ceph_argparse_witharg(args, i, &val, "-p", "--pool", (char*)NULL)) {
2551 pool_name = val;
2552 pool = rgw_pool(pool_name);
2553 } else if (ceph_argparse_witharg(args, i, &val, "-o", "--object", (char*)NULL)) {
2554 object = val;
2555 } else if (ceph_argparse_witharg(args, i, &val, "--object-version", (char*)NULL)) {
2556 object_version = val;
2557 } else if (ceph_argparse_witharg(args, i, &val, "--client-id", (char*)NULL)) {
2558 client_id = val;
2559 } else if (ceph_argparse_witharg(args, i, &val, "--op-id", (char*)NULL)) {
2560 op_id = val;
2561 } else if (ceph_argparse_witharg(args, i, &val, "--state", (char*)NULL)) {
2562 state_str = val;
2563 } else if (ceph_argparse_witharg(args, i, &val, "--op-mask", (char*)NULL)) {
2564 op_mask_str = val;
2565 } else if (ceph_argparse_witharg(args, i, &val, "--key-type", (char*)NULL)) {
2566 key_type_str = val;
2567 if (key_type_str.compare("swift") == 0) {
2568 key_type = KEY_TYPE_SWIFT;
2569 } else if (key_type_str.compare("s3") == 0) {
2570 key_type = KEY_TYPE_S3;
2571 } else {
2572 cerr << "bad key type: " << key_type_str << std::endl;
2573 return usage();
2574 }
2575 } else if (ceph_argparse_witharg(args, i, &val, "--job-id", (char*)NULL)) {
2576 job_id = val;
2577 } else if (ceph_argparse_binary_flag(args, i, &gen_access_key, NULL, "--gen-access-key", (char*)NULL)) {
2578 // do nothing
2579 } else if (ceph_argparse_binary_flag(args, i, &gen_secret_key, NULL, "--gen-secret", (char*)NULL)) {
2580 // do nothing
2581 } else if (ceph_argparse_binary_flag(args, i, &show_log_entries, NULL, "--show_log_entries", (char*)NULL)) {
2582 // do nothing
2583 } else if (ceph_argparse_binary_flag(args, i, &show_log_sum, NULL, "--show_log_sum", (char*)NULL)) {
2584 // do nothing
2585 } else if (ceph_argparse_binary_flag(args, i, &skip_zero_entries, NULL, "--skip_zero_entries", (char*)NULL)) {
2586 // do nothing
2587 } else if (ceph_argparse_binary_flag(args, i, &admin, NULL, "--admin", (char*)NULL)) {
2588 admin_specified = true;
2589 } else if (ceph_argparse_binary_flag(args, i, &system, NULL, "--system", (char*)NULL)) {
2590 system_specified = true;
2591 } else if (ceph_argparse_binary_flag(args, i, &verbose, NULL, "--verbose", (char*)NULL)) {
2592 // do nothing
2593 } else if (ceph_argparse_binary_flag(args, i, &staging, NULL, "--staging", (char*)NULL)) {
2594 // do nothing
2595 } else if (ceph_argparse_binary_flag(args, i, &commit, NULL, "--commit", (char*)NULL)) {
2596 // do nothing
2597 } else if (ceph_argparse_witharg(args, i, &tmp, errs, "-a", "--auth-uid", (char*)NULL)) {
2598 if (!errs.str().empty()) {
2599 cerr << errs.str() << std::endl;
2600 exit(EXIT_FAILURE);
2601 }
2602 } else if (ceph_argparse_witharg(args, i, &val, "--min-rewrite-size", (char*)NULL)) {
2603 min_rewrite_size = (uint64_t)atoll(val.c_str());
2604 } else if (ceph_argparse_witharg(args, i, &val, "--max-rewrite-size", (char*)NULL)) {
2605 max_rewrite_size = (uint64_t)atoll(val.c_str());
2606 } else if (ceph_argparse_witharg(args, i, &val, "--min-rewrite-stripe-size", (char*)NULL)) {
2607 min_rewrite_stripe_size = (uint64_t)atoll(val.c_str());
2608 } else if (ceph_argparse_witharg(args, i, &val, "--max-buckets", (char*)NULL)) {
2609 max_buckets = (int)strict_strtol(val.c_str(), 10, &err);
2610 if (!err.empty()) {
2611 cerr << "ERROR: failed to parse max buckets: " << err << std::endl;
2612 return EINVAL;
2613 }
2614 max_buckets_specified = true;
2615 } else if (ceph_argparse_witharg(args, i, &val, "--max-entries", (char*)NULL)) {
2616 max_entries = (int)strict_strtol(val.c_str(), 10, &err);
2617 if (!err.empty()) {
2618 cerr << "ERROR: failed to parse max entries: " << err << std::endl;
2619 return EINVAL;
2620 }
2621 } else if (ceph_argparse_witharg(args, i, &val, "--max-size", (char*)NULL)) {
2622 max_size = strict_si_cast<int64_t>(val.c_str(), &err);
2623 if (!err.empty()) {
2624 cerr << "ERROR: failed to parse max size: " << err << std::endl;
2625 return EINVAL;
2626 }
2627 have_max_size = true;
2628 } else if (ceph_argparse_witharg(args, i, &val, "--max-objects", (char*)NULL)) {
2629 max_objects = (int64_t)strict_strtoll(val.c_str(), 10, &err);
2630 if (!err.empty()) {
2631 cerr << "ERROR: failed to parse max objects: " << err << std::endl;
2632 return EINVAL;
2633 }
2634 have_max_objects = true;
2635 } else if (ceph_argparse_witharg(args, i, &val, "--date", "--time", (char*)NULL)) {
2636 date = val;
2637 if (end_date.empty())
2638 end_date = date;
2639 } else if (ceph_argparse_witharg(args, i, &val, "--start-date", "--start-time", (char*)NULL)) {
2640 start_date = val;
2641 } else if (ceph_argparse_witharg(args, i, &val, "--end-date", "--end-time", (char*)NULL)) {
2642 end_date = val;
2643 } else if (ceph_argparse_witharg(args, i, &val, "--num-shards", (char*)NULL)) {
2644 num_shards = (int)strict_strtol(val.c_str(), 10, &err);
2645 if (!err.empty()) {
2646 cerr << "ERROR: failed to parse num shards: " << err << std::endl;
2647 return EINVAL;
2648 }
2649 num_shards_specified = true;
2650 } else if (ceph_argparse_witharg(args, i, &val, "--max-concurrent-ios", (char*)NULL)) {
2651 max_concurrent_ios = (int)strict_strtol(val.c_str(), 10, &err);
2652 if (!err.empty()) {
2653 cerr << "ERROR: failed to parse max concurrent ios: " << err << std::endl;
2654 return EINVAL;
2655 }
2656 } else if (ceph_argparse_witharg(args, i, &val, "--orphan-stale-secs", (char*)NULL)) {
2657 orphan_stale_secs = (uint64_t)strict_strtoll(val.c_str(), 10, &err);
2658 if (!err.empty()) {
2659 cerr << "ERROR: failed to parse orphan stale secs: " << err << std::endl;
2660 return EINVAL;
2661 }
2662 } else if (ceph_argparse_witharg(args, i, &val, "--shard-id", (char*)NULL)) {
2663 shard_id = (int)strict_strtol(val.c_str(), 10, &err);
2664 if (!err.empty()) {
2665 cerr << "ERROR: failed to parse shard id: " << err << std::endl;
2666 return EINVAL;
2667 }
2668 specified_shard_id = true;
2669 } else if (ceph_argparse_witharg(args, i, &val, "--daemon-id", (char*)NULL)) {
2670 daemon_id = val;
2671 specified_daemon_id = true;
2672 } else if (ceph_argparse_witharg(args, i, &val, "--access", (char*)NULL)) {
2673 access = val;
2674 perm_mask = rgw_str_to_perm(access.c_str());
2675 set_perm = true;
2676 } else if (ceph_argparse_witharg(args, i, &val, "--temp-url-key", (char*)NULL)) {
2677 temp_url_keys[0] = val;
2678 set_temp_url_key = true;
2679 } else if (ceph_argparse_witharg(args, i, &val, "--temp-url-key2", "--temp-url-key-2", (char*)NULL)) {
2680 temp_url_keys[1] = val;
2681 set_temp_url_key = true;
2682 } else if (ceph_argparse_witharg(args, i, &val, "--bucket-id", (char*)NULL)) {
2683 bucket_id = val;
2684 if (bucket_id.empty()) {
2685 cerr << "bad bucket-id" << std::endl;
2686 return usage();
2687 }
2688 } else if (ceph_argparse_witharg(args, i, &val, "--format", (char*)NULL)) {
2689 format = val;
2690 } else if (ceph_argparse_witharg(args, i, &val, "--categories", (char*)NULL)) {
2691 string cat_str = val;
2692 list<string> cat_list;
2693 list<string>::iterator iter;
2694 get_str_list(cat_str, cat_list);
2695 for (iter = cat_list.begin(); iter != cat_list.end(); ++iter) {
2696 categories[*iter] = true;
2697 }
2698 } else if (ceph_argparse_binary_flag(args, i, &delete_child_objects, NULL, "--purge-objects", (char*)NULL)) {
2699 // do nothing
2700 } else if (ceph_argparse_binary_flag(args, i, &pretty_format, NULL, "--pretty-format", (char*)NULL)) {
2701 // do nothing
2702 } else if (ceph_argparse_binary_flag(args, i, &purge_data, NULL, "--purge-data", (char*)NULL)) {
2703 delete_child_objects = purge_data;
2704 } else if (ceph_argparse_binary_flag(args, i, &purge_keys, NULL, "--purge-keys", (char*)NULL)) {
2705 // do nothing
2706 } else if (ceph_argparse_binary_flag(args, i, &yes_i_really_mean_it, NULL, "--yes-i-really-mean-it", (char*)NULL)) {
2707 // do nothing
2708 } else if (ceph_argparse_binary_flag(args, i, &fix, NULL, "--fix", (char*)NULL)) {
2709 // do nothing
2710 } else if (ceph_argparse_binary_flag(args, i, &remove_bad, NULL, "--remove-bad", (char*)NULL)) {
2711 // do nothing
2712 } else if (ceph_argparse_binary_flag(args, i, &check_head_obj_locator, NULL, "--check-head-obj-locator", (char*)NULL)) {
2713 // do nothing
2714 } else if (ceph_argparse_binary_flag(args, i, &check_objects, NULL, "--check-objects", (char*)NULL)) {
2715 // do nothing
2716 } else if (ceph_argparse_binary_flag(args, i, &sync_stats, NULL, "--sync-stats", (char*)NULL)) {
2717 // do nothing
2718 } else if (ceph_argparse_binary_flag(args, i, &include_all, NULL, "--include-all", (char*)NULL)) {
2719 // do nothing
2720 } else if (ceph_argparse_binary_flag(args, i, &extra_info, NULL, "--extra-info", (char*)NULL)) {
2721 // do nothing
2722 } else if (ceph_argparse_binary_flag(args, i, &bypass_gc, NULL, "--bypass-gc", (char*)NULL)) {
2723 // do nothing
2724 } else if (ceph_argparse_binary_flag(args, i, &warnings_only, NULL, "--warnings-only", (char*)NULL)) {
2725 // do nothing
2726 } else if (ceph_argparse_binary_flag(args, i, &inconsistent_index, NULL, "--inconsistent-index", (char*)NULL)) {
2727 // do nothing
2728 } else if (ceph_argparse_witharg(args, i, &val, "--caps", (char*)NULL)) {
2729 caps = val;
2730 } else if (ceph_argparse_witharg(args, i, &val, "-i", "--infile", (char*)NULL)) {
2731 infile = val;
2732 } else if (ceph_argparse_witharg(args, i, &val, "--metadata-key", (char*)NULL)) {
2733 metadata_key = val;
2734 } else if (ceph_argparse_witharg(args, i, &val, "--marker", (char*)NULL)) {
2735 marker = val;
2736 } else if (ceph_argparse_witharg(args, i, &val, "--start-marker", (char*)NULL)) {
2737 start_marker = val;
2738 } else if (ceph_argparse_witharg(args, i, &val, "--end-marker", (char*)NULL)) {
2739 end_marker = val;
2740 } else if (ceph_argparse_witharg(args, i, &val, "--quota-scope", (char*)NULL)) {
2741 quota_scope = val;
2742 } else if (ceph_argparse_witharg(args, i, &val, "--replica-log-type", (char*)NULL)) {
2743 replica_log_type_str = val;
2744 replica_log_type = get_replicalog_type(replica_log_type_str);
2745 if (replica_log_type == ReplicaLog_Invalid) {
2746 cerr << "ERROR: invalid replica log type" << std::endl;
2747 return EINVAL;
2748 }
2749 } else if (ceph_argparse_witharg(args, i, &val, "--index-type", (char*)NULL)) {
2750 string index_type_str = val;
2751 bi_index_type = get_bi_index_type(index_type_str);
2752 if (bi_index_type == InvalidIdx) {
2753 cerr << "ERROR: invalid bucket index entry type" << std::endl;
2754 return EINVAL;
2755 }
2756 } else if (ceph_argparse_binary_flag(args, i, &is_master_int, NULL, "--master", (char*)NULL)) {
2757 is_master = (bool)is_master_int;
2758 is_master_set = true;
2759 } else if (ceph_argparse_binary_flag(args, i, &set_default, NULL, "--default", (char*)NULL)) {
2760 /* do nothing */
2761 } else if (ceph_argparse_binary_flag(args, i, &read_only_int, NULL, "--read-only", (char*)NULL)) {
2762 read_only = (bool)read_only_int;
2763 is_read_only_set = true;
2764 } else if (ceph_argparse_witharg(args, i, &val, "--master-url", (char*)NULL)) {
2765 master_url = val;
2766 } else if (ceph_argparse_witharg(args, i, &val, "--master-zonegroup", (char*)NULL)) {
2767 master_zonegroup = val;
2768 } else if (ceph_argparse_witharg(args, i, &val, "--master-zone", (char*)NULL)) {
2769 master_zone = val;
2770 } else if (ceph_argparse_witharg(args, i, &val, "--period", (char*)NULL)) {
2771 period_id = val;
2772 } else if (ceph_argparse_witharg(args, i, &val, "--epoch", (char*)NULL)) {
2773 period_epoch = val;
2774 } else if (ceph_argparse_witharg(args, i, &val, "--remote", (char*)NULL)) {
2775 remote = val;
2776 } else if (ceph_argparse_witharg(args, i, &val, "--url", (char*)NULL)) {
2777 url = val;
2778 } else if (ceph_argparse_witharg(args, i, &val, "--realm-id", (char*)NULL)) {
2779 realm_id = val;
2780 } else if (ceph_argparse_witharg(args, i, &val, "--realm-new-name", (char*)NULL)) {
2781 realm_new_name = val;
2782 } else if (ceph_argparse_witharg(args, i, &val, "--zonegroup-id", (char*)NULL)) {
2783 zonegroup_id = val;
2784 } else if (ceph_argparse_witharg(args, i, &val, "--zonegroup-new-name", (char*)NULL)) {
2785 zonegroup_new_name = val;
2786 } else if (ceph_argparse_witharg(args, i, &val, "--placement-id", (char*)NULL)) {
2787 placement_id = val;
2788 } else if (ceph_argparse_witharg(args, i, &val, "--tags", (char*)NULL)) {
2789 get_str_list(val, tags);
2790 } else if (ceph_argparse_witharg(args, i, &val, "--tags-add", (char*)NULL)) {
2791 get_str_list(val, tags_add);
2792 } else if (ceph_argparse_witharg(args, i, &val, "--tags-rm", (char*)NULL)) {
2793 get_str_list(val, tags_rm);
2794 } else if (ceph_argparse_witharg(args, i, &val, "--api-name", (char*)NULL)) {
2795 api_name = val;
2796 } else if (ceph_argparse_witharg(args, i, &val, "--zone-id", (char*)NULL)) {
2797 zone_id = val;
2798 } else if (ceph_argparse_witharg(args, i, &val, "--zone-new-name", (char*)NULL)) {
2799 zone_new_name = val;
2800 } else if (ceph_argparse_witharg(args, i, &val, "--endpoints", (char*)NULL)) {
2801 get_str_list(val, endpoints);
2802 } else if (ceph_argparse_witharg(args, i, &val, "--sync-from", (char*)NULL)) {
2803 get_str_list(val, sync_from);
2804 } else if (ceph_argparse_witharg(args, i, &val, "--sync-from-rm", (char*)NULL)) {
2805 get_str_list(val, sync_from_rm);
2806 } else if (ceph_argparse_binary_flag(args, i, &tmp_int, NULL, "--sync-from-all", (char*)NULL)) {
2807 sync_from_all = (bool)tmp_int;
2808 sync_from_all_specified = true;
2809 } else if (ceph_argparse_witharg(args, i, &val, "--source-zone", (char*)NULL)) {
2810 source_zone_name = val;
2811 } else if (ceph_argparse_witharg(args, i, &val, "--tier-type", (char*)NULL)) {
2812 tier_type = val;
2813 tier_type_specified = true;
2814 } else if (ceph_argparse_witharg(args, i, &val, "--tier-config", (char*)NULL)) {
2815 parse_tier_config_param(val, tier_config_add);
2816 } else if (ceph_argparse_witharg(args, i, &val, "--tier-config-rm", (char*)NULL)) {
2817 parse_tier_config_param(val, tier_config_rm);
2818 } else if (ceph_argparse_witharg(args, i, &val, "--index-pool", (char*)NULL)) {
2819 index_pool = val;
2820 } else if (ceph_argparse_witharg(args, i, &val, "--data-pool", (char*)NULL)) {
2821 data_pool = val;
2822 } else if (ceph_argparse_witharg(args, i, &val, "--data-extra-pool", (char*)NULL)) {
2823 data_extra_pool = val;
2824 } else if (ceph_argparse_witharg(args, i, &val, "--placement-index-type", (char*)NULL)) {
2825 if (val == "normal") {
2826 placement_index_type = RGWBIType_Normal;
2827 } else if (val == "indexless") {
2828 placement_index_type = RGWBIType_Indexless;
2829 } else {
2830 placement_index_type = (RGWBucketIndexType)strict_strtol(val.c_str(), 10, &err);
2831 if (!err.empty()) {
2832 cerr << "ERROR: failed to parse index type index: " << err << std::endl;
2833 return EINVAL;
2834 }
2835 }
2836 index_type_specified = true;
2837 } else if (ceph_argparse_witharg(args, i, &val, "--compression", (char*)NULL)) {
2838 compression_type = val;
2839 } else if (ceph_argparse_witharg(args, i, &val, "--role-name", (char*)NULL)) {
2840 role_name = val;
2841 } else if (ceph_argparse_witharg(args, i, &val, "--path", (char*)NULL)) {
2842 path = val;
2843 } else if (ceph_argparse_witharg(args, i, &val, "--assume-role-policy-doc", (char*)NULL)) {
2844 assume_role_doc = val;
2845 } else if (ceph_argparse_witharg(args, i, &val, "--policy-name", (char*)NULL)) {
2846 policy_name = val;
2847 } else if (ceph_argparse_witharg(args, i, &val, "--policy-doc", (char*)NULL)) {
2848 perm_policy_doc = val;
2849 } else if (ceph_argparse_witharg(args, i, &val, "--path-prefix", (char*)NULL)) {
2850 path_prefix = val;
2851 } else if (strncmp(*i, "-", 1) == 0) {
2852 cerr << "ERROR: invalid flag " << *i << std::endl;
2853 return EINVAL;
2854 } else {
2855 ++i;
2856 }
2857 }
2858 if (tenant.empty()) {
2859 tenant = user_id.tenant;
2860 } else {
2861 if (user_id.empty()) {
2862 cerr << "ERROR: --tenant is set, but there's no user ID" << std::endl;
2863 return EINVAL;
2864 }
2865 user_id.tenant = tenant;
2866 }
2867
2868 if (args.empty()) {
2869 return usage();
2870 }
2871 else {
2872 const char *prev_cmd = NULL;
2873 const char *prev_prev_cmd = NULL;
2874 std::vector<const char*>::iterator i ;
2875 for (i = args.begin(); i != args.end(); ++i) {
2876 opt_cmd = get_cmd(*i, prev_cmd, prev_prev_cmd, &need_more);
2877 if (opt_cmd < 0) {
2878 cerr << "unrecognized arg " << *i << std::endl;
2879 return usage();
2880 }
2881 if (!need_more) {
2882 ++i;
2883 break;
2884 }
2885 prev_prev_cmd = prev_cmd;
2886 prev_cmd = *i;
2887 }
2888
2889 if (opt_cmd == OPT_NO_CMD)
2890 return usage();
2891
2892 /* some commands may have an optional extra param */
2893 if (i != args.end()) {
2894 switch (opt_cmd) {
2895 case OPT_METADATA_GET:
2896 case OPT_METADATA_PUT:
2897 case OPT_METADATA_RM:
2898 case OPT_METADATA_LIST:
2899 metadata_key = *i;
2900 break;
2901 default:
2902 break;
2903 }
2904 }
2905
2906 /* check key parameter conflict */
2907 if ((!access_key.empty()) && gen_access_key) {
2908 cerr << "ERROR: key parameter conflict, --access-key & --gen-access-key" << std::endl;
2909 return EINVAL;
2910 }
2911 if ((!secret_key.empty()) && gen_secret_key) {
2912 cerr << "ERROR: key parameter conflict, --secret & --gen-secret" << std::endl;
2913 return EINVAL;
2914 }
2915 }
2916
2917 // default to pretty json
2918 if (format.empty()) {
2919 format = "json";
2920 pretty_format = true;
2921 }
2922
2923 if (format == "xml")
2924 formatter = new XMLFormatter(pretty_format);
2925 else if (format == "json")
2926 formatter = new JSONFormatter(pretty_format);
2927 else {
2928 cerr << "unrecognized format: " << format << std::endl;
2929 return usage();
2930 }
2931
2932 realm_name = g_conf->rgw_realm;
2933 zone_name = g_conf->rgw_zone;
2934 zonegroup_name = g_conf->rgw_zonegroup;
2935
2936 RGWStreamFlusher f(formatter, cout);
2937
2938 // not a raw op if 'period update' needs to commit to master
2939 bool raw_period_update = opt_cmd == OPT_PERIOD_UPDATE && !commit;
2940 std::set<int> raw_storage_ops_list = {OPT_ZONEGROUP_ADD, OPT_ZONEGROUP_CREATE, OPT_ZONEGROUP_DELETE,
2941 OPT_ZONEGROUP_GET, OPT_ZONEGROUP_LIST,
2942 OPT_ZONEGROUP_SET, OPT_ZONEGROUP_DEFAULT,
2943 OPT_ZONEGROUP_RENAME, OPT_ZONEGROUP_MODIFY,
2944 OPT_ZONEGROUP_REMOVE,
2945 OPT_ZONEGROUP_PLACEMENT_ADD, OPT_ZONEGROUP_PLACEMENT_RM,
2946 OPT_ZONEGROUP_PLACEMENT_MODIFY, OPT_ZONEGROUP_PLACEMENT_LIST,
2947 OPT_ZONEGROUP_PLACEMENT_DEFAULT,
2948 OPT_ZONE_CREATE, OPT_ZONE_DELETE,
2949 OPT_ZONE_GET, OPT_ZONE_SET, OPT_ZONE_RENAME,
2950 OPT_ZONE_LIST, OPT_ZONE_MODIFY, OPT_ZONE_DEFAULT,
2951 OPT_ZONE_PLACEMENT_ADD, OPT_ZONE_PLACEMENT_RM,
2952 OPT_ZONE_PLACEMENT_MODIFY, OPT_ZONE_PLACEMENT_LIST,
2953 OPT_REALM_CREATE,
2954 OPT_PERIOD_DELETE, OPT_PERIOD_GET,
2955 OPT_PERIOD_PULL,
2956 OPT_PERIOD_GET_CURRENT, OPT_PERIOD_LIST,
2957 OPT_GLOBAL_QUOTA_GET, OPT_GLOBAL_QUOTA_SET,
2958 OPT_GLOBAL_QUOTA_ENABLE, OPT_GLOBAL_QUOTA_DISABLE,
2959 OPT_REALM_DELETE, OPT_REALM_GET, OPT_REALM_LIST,
2960 OPT_REALM_LIST_PERIODS,
2961 OPT_REALM_GET_DEFAULT, OPT_REALM_REMOVE,
2962 OPT_REALM_RENAME, OPT_REALM_SET,
2963 OPT_REALM_DEFAULT, OPT_REALM_PULL};
2964
2965
2966 bool raw_storage_op = (raw_storage_ops_list.find(opt_cmd) != raw_storage_ops_list.end() ||
2967 raw_period_update);
2968
2969 if (raw_storage_op) {
2970 store = RGWStoreManager::get_raw_storage(g_ceph_context);
2971 } else {
2972 store = RGWStoreManager::get_storage(g_ceph_context, false, false, false, false);
2973 }
2974 if (!store) {
2975 cerr << "couldn't init storage provider" << std::endl;
2976 return 5; //EIO
2977 }
2978
2979 if (!source_zone_name.empty()) {
2980 if (!store->find_zone_id_by_name(source_zone_name, &source_zone)) {
2981 cerr << "WARNING: cannot find source zone id for name=" << source_zone_name << std::endl;
2982 source_zone = source_zone_name;
2983 }
2984 }
2985
2986 rgw_user_init(store);
2987 rgw_bucket_init(store->meta_mgr);
2988
2989 StoreDestructor store_destructor(store);
2990
2991 if (raw_storage_op) {
2992 switch (opt_cmd) {
2993 case OPT_PERIOD_DELETE:
2994 {
2995 if (period_id.empty()) {
2996 cerr << "missing period id" << std::endl;
2997 return EINVAL;
2998 }
2999 RGWPeriod period(period_id);
3000 int ret = period.init(g_ceph_context, store);
3001 if (ret < 0) {
3002 cerr << "period.init failed: " << cpp_strerror(-ret) << std::endl;
3003 return -ret;
3004 }
3005 ret = period.delete_obj();
3006 if (ret < 0) {
3007 cerr << "ERROR: couldn't delete period: " << cpp_strerror(-ret) << std::endl;
3008 return -ret;
3009 }
3010
3011 }
3012 break;
3013 case OPT_PERIOD_GET:
3014 {
3015 epoch_t epoch = 0;
3016 if (!period_epoch.empty()) {
3017 epoch = atoi(period_epoch.c_str());
3018 }
3019 if (staging) {
3020 RGWRealm realm(realm_id, realm_name);
3021 int ret = realm.init(g_ceph_context, store);
3022 if (ret < 0 ) {
3023 cerr << "Error initializing realm " << cpp_strerror(-ret) << std::endl;
3024 return -ret;
3025 }
3026 realm_id = realm.get_id();
3027 realm_name = realm.get_name();
3028 period_id = RGWPeriod::get_staging_id(realm_id);
3029 epoch = 1;
3030 }
3031 RGWPeriod period(period_id, epoch);
3032 int ret = period.init(g_ceph_context, store, realm_id, realm_name);
3033 if (ret < 0) {
3034 cerr << "period init failed: " << cpp_strerror(-ret) << std::endl;
3035 return -ret;
3036 }
3037 encode_json("period", period, formatter);
3038 formatter->flush(cout);
3039 cout << std::endl;
3040 }
3041 break;
3042 case OPT_PERIOD_GET_CURRENT:
3043 {
3044 int ret = read_current_period_id(store, realm_id, realm_name, &period_id);
3045 if (ret < 0) {
3046 return -ret;
3047 }
3048 formatter->open_object_section("period_get_current");
3049 encode_json("current_period", period_id, formatter);
3050 formatter->close_section();
3051 formatter->flush(cout);
3052 }
3053 break;
3054 case OPT_PERIOD_LIST:
3055 {
3056 list<string> periods;
3057 int ret = store->list_periods(periods);
3058 if (ret < 0) {
3059 cerr << "failed to list periods: " << cpp_strerror(-ret) << std::endl;
3060 return -ret;
3061 }
3062 formatter->open_object_section("periods_list");
3063 encode_json("periods", periods, formatter);
3064 formatter->close_section();
3065 formatter->flush(cout);
3066 cout << std::endl;
3067 }
3068 break;
3069 case OPT_PERIOD_UPDATE:
3070 {
3071 int ret = update_period(realm_id, realm_name, period_id, period_epoch,
3072 commit, remote, url, access_key, secret_key,
3073 formatter, yes_i_really_mean_it);
3074 if (ret < 0) {
3075 return -ret;
3076 }
3077 }
3078 break;
3079 case OPT_PERIOD_PULL:
3080 {
3081 boost::optional<RGWRESTConn> conn;
3082 RGWRESTConn *remote_conn = nullptr;
3083 if (url.empty()) {
3084 // load current period for endpoints
3085 RGWRealm realm(realm_id, realm_name);
3086 int ret = realm.init(g_ceph_context, store);
3087 if (ret < 0) {
3088 cerr << "failed to init realm: " << cpp_strerror(-ret) << std::endl;
3089 return -ret;
3090 }
3091 RGWPeriod current_period(realm.get_current_period());
3092 ret = current_period.init(g_ceph_context, store);
3093 if (ret < 0) {
3094 cerr << "failed to init current period: " << cpp_strerror(-ret) << std::endl;
3095 return -ret;
3096 }
3097 if (remote.empty()) {
3098 // use realm master zone as remote
3099 remote = current_period.get_master_zone();
3100 }
3101 conn = get_remote_conn(store, current_period.get_map(), remote);
3102 if (!conn) {
3103 cerr << "failed to find a zone or zonegroup for remote "
3104 << remote << std::endl;
3105 return -ENOENT;
3106 }
3107 remote_conn = &*conn;
3108 }
3109
3110 RGWPeriod period;
3111 int ret = do_period_pull(remote_conn, url, access_key, secret_key,
3112 realm_id, realm_name, period_id, period_epoch,
3113 &period);
3114 if (ret < 0) {
3115 cerr << "period pull failed: " << cpp_strerror(-ret) << std::endl;
3116 return -ret;
3117 }
3118
3119 encode_json("period", period, formatter);
3120 formatter->flush(cout);
3121 cout << std::endl;
3122 }
3123 break;
3124 case OPT_GLOBAL_QUOTA_GET:
3125 case OPT_GLOBAL_QUOTA_SET:
3126 case OPT_GLOBAL_QUOTA_ENABLE:
3127 case OPT_GLOBAL_QUOTA_DISABLE:
3128 {
3129 if (realm_id.empty()) {
3130 RGWRealm realm(g_ceph_context, store);
3131 if (!realm_name.empty()) {
3132 // look up realm_id for the given realm_name
3133 int ret = realm.read_id(realm_name, realm_id);
3134 if (ret < 0) {
3135 cerr << "ERROR: failed to read realm for " << realm_name
3136 << ": " << cpp_strerror(-ret) << std::endl;
3137 return -ret;
3138 }
3139 } else {
3140 // use default realm_id when none is given
3141 int ret = realm.read_default_id(realm_id);
3142 if (ret < 0 && ret != -ENOENT) { // on ENOENT, use empty realm_id
3143 cerr << "ERROR: failed to read default realm: "
3144 << cpp_strerror(-ret) << std::endl;
3145 return -ret;
3146 }
3147 }
3148 }
3149
3150 RGWPeriodConfig period_config;
3151 int ret = period_config.read(store, realm_id);
3152 if (ret < 0 && ret != -ENOENT) {
3153 cerr << "ERROR: failed to read period config: "
3154 << cpp_strerror(-ret) << std::endl;
3155 return -ret;
3156 }
3157
3158 formatter->open_object_section("period_config");
3159 if (quota_scope == "bucket") {
3160 set_quota_info(period_config.bucket_quota, opt_cmd,
3161 max_size, max_objects,
3162 have_max_size, have_max_objects);
3163 encode_json("bucket quota", period_config.bucket_quota, formatter);
3164 } else if (quota_scope == "user") {
3165 set_quota_info(period_config.user_quota, opt_cmd,
3166 max_size, max_objects,
3167 have_max_size, have_max_objects);
3168 encode_json("user quota", period_config.user_quota, formatter);
3169 } else if (quota_scope.empty() && opt_cmd == OPT_GLOBAL_QUOTA_GET) {
3170 // if no scope is given for GET, print both
3171 encode_json("bucket quota", period_config.bucket_quota, formatter);
3172 encode_json("user quota", period_config.user_quota, formatter);
3173 } else {
3174 cerr << "ERROR: invalid quota scope specification. Please specify "
3175 "either --quota-scope=bucket, or --quota-scope=user" << std::endl;
3176 return EINVAL;
3177 }
3178 formatter->close_section();
3179
3180 if (opt_cmd != OPT_GLOBAL_QUOTA_GET) {
3181 // write the modified period config
3182 ret = period_config.write(store, realm_id);
3183 if (ret < 0) {
3184 cerr << "ERROR: failed to write period config: "
3185 << cpp_strerror(-ret) << std::endl;
3186 return -ret;
3187 }
3188 if (!realm_id.empty()) {
3189 cout << "Global quota changes saved. Use 'period update' to apply "
3190 "them to the staging period, and 'period commit' to commit the "
3191 "new period." << std::endl;
3192 } else {
3193 cout << "Global quota changes saved. They will take effect as "
3194 "the gateways are restarted." << std::endl;
3195 }
3196 }
3197
3198 formatter->flush(cout);
3199 cout << std::endl;
3200 }
3201 break;
3202 case OPT_REALM_CREATE:
3203 {
3204 if (realm_name.empty()) {
3205 cerr << "missing realm name" << std::endl;
3206 return EINVAL;
3207 }
3208
3209 RGWRealm realm(realm_name, g_ceph_context, store);
3210 int ret = realm.create();
3211 if (ret < 0) {
3212 cerr << "ERROR: couldn't create realm " << realm_name << ": " << cpp_strerror(-ret) << std::endl;
3213 return -ret;
3214 }
3215
3216 if (set_default) {
3217 ret = realm.set_as_default();
3218 if (ret < 0) {
3219 cerr << "failed to set realm " << realm_name << " as default: " << cpp_strerror(-ret) << std::endl;
3220 }
3221 }
3222
3223 encode_json("realm", realm, formatter);
3224 formatter->flush(cout);
3225 cout << std::endl;
3226 }
3227 break;
3228 case OPT_REALM_DELETE:
3229 {
3230 RGWRealm realm(realm_id, realm_name);
3231 if (realm_name.empty() && realm_id.empty()) {
3232 cerr << "missing realm name or id" << std::endl;
3233 return EINVAL;
3234 }
3235 int ret = realm.init(g_ceph_context, store);
3236 if (ret < 0) {
3237 cerr << "realm.init failed: " << cpp_strerror(-ret) << std::endl;
3238 return -ret;
3239 }
3240 ret = realm.delete_obj();
3241 if (ret < 0) {
3242 cerr << "ERROR: couldn't : " << cpp_strerror(-ret) << std::endl;
3243 return -ret;
3244 }
3245
3246 }
3247 break;
3248 case OPT_REALM_GET:
3249 {
3250 RGWRealm realm(realm_id, realm_name);
3251 int ret = realm.init(g_ceph_context, store);
3252 if (ret < 0) {
3253 if (ret == -ENOENT && realm_name.empty() && realm_id.empty()) {
3254 cerr << "missing realm name or id, or default realm not found" << std::endl;
3255 } else {
3256 cerr << "realm.init failed: " << cpp_strerror(-ret) << std::endl;
3257 }
3258 return -ret;
3259 }
3260 encode_json("realm", realm, formatter);
3261 formatter->flush(cout);
3262 cout << std::endl;
3263 }
3264 break;
3265 case OPT_REALM_GET_DEFAULT:
3266 {
3267 RGWRealm realm(g_ceph_context, store);
3268 string default_id;
3269 int ret = realm.read_default_id(default_id);
3270 if (ret == -ENOENT) {
3271 cout << "No default realm is set" << std::endl;
3272 return -ret;
3273 } else if (ret < 0) {
3274 cerr << "Error reading default realm:" << cpp_strerror(-ret) << std::endl;
3275 return -ret;
3276 }
3277 cout << "default realm: " << default_id << std::endl;
3278 }
3279 break;
3280 case OPT_REALM_LIST:
3281 {
3282 RGWRealm realm(g_ceph_context, store);
3283 string default_id;
3284 int ret = realm.read_default_id(default_id);
3285 if (ret < 0 && ret != -ENOENT) {
3286 cerr << "could not determine default realm: " << cpp_strerror(-ret) << std::endl;
3287 }
3288 list<string> realms;
3289 ret = store->list_realms(realms);
3290 if (ret < 0) {
3291 cerr << "failed to list realms: " << cpp_strerror(-ret) << std::endl;
3292 return -ret;
3293 }
3294 formatter->open_object_section("realms_list");
3295 encode_json("default_info", default_id, formatter);
3296 encode_json("realms", realms, formatter);
3297 formatter->close_section();
3298 formatter->flush(cout);
3299 cout << std::endl;
3300 }
3301 break;
3302 case OPT_REALM_LIST_PERIODS:
3303 {
3304 int ret = read_current_period_id(store, realm_id, realm_name, &period_id);
3305 if (ret < 0) {
3306 return -ret;
3307 }
3308 list<string> periods;
3309 ret = store->list_periods(period_id, periods);
3310 if (ret < 0) {
3311 cerr << "list periods failed: " << cpp_strerror(-ret) << std::endl;
3312 return -ret;
3313 }
3314 formatter->open_object_section("realm_periods_list");
3315 encode_json("current_period", period_id, formatter);
3316 encode_json("periods", periods, formatter);
3317 formatter->close_section();
3318 formatter->flush(cout);
3319 cout << std::endl;
3320 }
3321 break;
3322
3323 case OPT_REALM_RENAME:
3324 {
3325 RGWRealm realm(realm_id, realm_name);
3326 if (realm_new_name.empty()) {
3327 cerr << "missing realm new name" << std::endl;
3328 return EINVAL;
3329 }
3330 if (realm_name.empty() && realm_id.empty()) {
3331 cerr << "missing realm name or id" << std::endl;
3332 return EINVAL;
3333 }
3334 int ret = realm.init(g_ceph_context, store);
3335 if (ret < 0) {
3336 cerr << "realm.init failed: " << cpp_strerror(-ret) << std::endl;
3337 return -ret;
3338 }
3339 ret = realm.rename(realm_new_name);
3340 if (ret < 0) {
3341 cerr << "realm.rename failed: " << cpp_strerror(-ret) << std::endl;
3342 return -ret;
3343 }
3344 cout << "Realm name updated. Note that this change only applies to "
3345 "the current cluster, so this command must be run separately "
3346 "on each of the realm's other clusters." << std::endl;
3347 }
3348 break;
3349 case OPT_REALM_SET:
3350 {
3351 if (realm_id.empty() && realm_name.empty()) {
3352 cerr << "no realm name or id provided" << std::endl;
3353 return EINVAL;
3354 }
3355 RGWRealm realm(realm_id, realm_name);
3356 bool new_realm = false;
3357 int ret = realm.init(g_ceph_context, store);
3358 if (ret < 0 && ret != -ENOENT) {
3359 cerr << "failed to init realm: " << cpp_strerror(-ret) << std::endl;
3360 return -ret;
3361 } else if (ret == -ENOENT) {
3362 new_realm = true;
3363 }
3364 ret = read_decode_json(infile, realm);
3365 if (ret < 0) {
3366 return 1;
3367 }
3368 if (!realm_name.empty() && realm.get_name() != realm_name) {
3369 cerr << "mismatch between --rgw-realm " << realm_name << " and json input file name " <<
3370 realm.get_name() << std::endl;
3371 return EINVAL;
3372 }
3373 /* new realm */
3374 if (new_realm) {
3375 cout << "clearing period and epoch for new realm" << std::endl;
3376 realm.clear_current_period_and_epoch();
3377 ret = realm.create();
3378 if (ret < 0) {
3379 cerr << "ERROR: couldn't create new realm: " << cpp_strerror(-ret) << std::endl;
3380 return 1;
3381 }
3382 } else {
3383 ret = realm.update();
3384 if (ret < 0) {
3385 cerr << "ERROR: couldn't store realm info: " << cpp_strerror(-ret) << std::endl;
3386 return 1;
3387 }
3388 }
3389
3390 if (set_default) {
3391 ret = realm.set_as_default();
3392 if (ret < 0) {
3393 cerr << "failed to set realm " << realm_name << " as default: " << cpp_strerror(-ret) << std::endl;
3394 }
3395 }
3396 encode_json("realm", realm, formatter);
3397 formatter->flush(cout);
3398 }
3399 break;
3400
3401 case OPT_REALM_DEFAULT:
3402 {
3403 RGWRealm realm(realm_id, realm_name);
3404 int ret = realm.init(g_ceph_context, store);
3405 if (ret < 0) {
3406 cerr << "failed to init realm: " << cpp_strerror(-ret) << std::endl;
3407 return -ret;
3408 }
3409 ret = realm.set_as_default();
3410 if (ret < 0) {
3411 cerr << "failed to set realm as default: " << cpp_strerror(-ret) << std::endl;
3412 return -ret;
3413 }
3414 }
3415 break;
3416 case OPT_REALM_PULL:
3417 {
3418 if (url.empty()) {
3419 cerr << "A --url must be provided." << std::endl;
3420 return EINVAL;
3421 }
3422 RGWEnv env;
3423 req_info info(g_ceph_context, &env);
3424 info.method = "GET";
3425 info.request_uri = "/admin/realm";
3426
3427 map<string, string> &params = info.args.get_params();
3428 if (!realm_id.empty())
3429 params["id"] = realm_id;
3430 if (!realm_name.empty())
3431 params["name"] = realm_name;
3432
3433 bufferlist bl;
3434 JSONParser p;
3435 int ret = send_to_url(url, access_key, secret_key, info, bl, p);
3436 if (ret < 0) {
3437 cerr << "request failed: " << cpp_strerror(-ret) << std::endl;
3438 if (ret == -EACCES) {
3439 cerr << "If the realm has been changed on the master zone, the "
3440 "master zone's gateway may need to be restarted to recognize "
3441 "this user." << std::endl;
3442 }
3443 return -ret;
3444 }
3445 RGWRealm realm;
3446 realm.init(g_ceph_context, store, false);
3447 try {
3448 decode_json_obj(realm, &p);
3449 } catch (JSONDecoder::err& e) {
3450 cerr << "failed to decode JSON response: " << e.message << std::endl;
3451 return EINVAL;
3452 }
3453 RGWPeriod period;
3454 auto& current_period = realm.get_current_period();
3455 if (!current_period.empty()) {
3456 // pull the latest epoch of the realm's current period
3457 ret = do_period_pull(nullptr, url, access_key, secret_key,
3458 realm_id, realm_name, current_period, "",
3459 &period);
3460 if (ret < 0) {
3461 cerr << "could not fetch period " << current_period << std::endl;
3462 return -ret;
3463 }
3464 }
3465 ret = realm.create(false);
3466 if (ret < 0 && ret != -EEXIST) {
3467 cerr << "Error storing realm " << realm.get_id() << ": "
3468 << cpp_strerror(ret) << std::endl;
3469 return -ret;
3470 } else if (ret ==-EEXIST) {
3471 ret = realm.update();
3472 if (ret < 0) {
3473 cerr << "Error storing realm " << realm.get_id() << ": "
3474 << cpp_strerror(ret) << std::endl;
3475 }
3476 }
3477
3478 if (set_default) {
3479 ret = realm.set_as_default();
3480 if (ret < 0) {
3481 cerr << "failed to set realm " << realm_name << " as default: " << cpp_strerror(-ret) << std::endl;
3482 }
3483 }
3484
3485 encode_json("realm", realm, formatter);
3486 formatter->flush(cout);
3487 cout << std::endl;
3488 }
3489 return 0;
3490
3491 case OPT_ZONEGROUP_ADD:
3492 {
3493 if (zonegroup_id.empty() && zonegroup_name.empty()) {
3494 cerr << "no zonegroup name or id provided" << std::endl;
3495 return EINVAL;
3496 }
3497
3498 RGWZoneGroup zonegroup(zonegroup_id,zonegroup_name);
3499 int ret = zonegroup.init(g_ceph_context, store);
3500 if (ret < 0) {
3501 cerr << "failed to initialize zonegroup " << zonegroup_name << " id " << zonegroup_id << " :"
3502 << cpp_strerror(-ret) << std::endl;
3503 return -ret;
3504 }
3505 RGWZoneParams zone(zone_id, zone_name);
3506 ret = zone.init(g_ceph_context, store);
3507 if (ret < 0) {
3508 cerr << "unable to initialize zone: " << cpp_strerror(-ret) << std::endl;
3509 return -ret;
3510 }
3511 string *ptier_type = (tier_type_specified ? &tier_type : nullptr);
3512 zone.tier_config = tier_config_add;
3513
3514 bool *psync_from_all = (sync_from_all_specified ? &sync_from_all : nullptr);
3515
3516 ret = zonegroup.add_zone(zone,
3517 (is_master_set ? &is_master : NULL),
3518 (is_read_only_set ? &read_only : NULL),
3519 endpoints, ptier_type,
3520 psync_from_all, sync_from, sync_from_rm);
3521 if (ret < 0) {
3522 cerr << "failed to add zone " << zone_name << " to zonegroup " << zonegroup.get_name() << ": "
3523 << cpp_strerror(-ret) << std::endl;
3524 return -ret;
3525 }
3526
3527 encode_json("zonegroup", zonegroup, formatter);
3528 formatter->flush(cout);
3529 }
3530 break;
3531 case OPT_ZONEGROUP_CREATE:
3532 {
3533 if (zonegroup_name.empty()) {
3534 cerr << "Missing zonegroup name" << std::endl;
3535 return EINVAL;
3536 }
3537 RGWRealm realm(realm_id, realm_name);
3538 int ret = realm.init(g_ceph_context, store);
3539 if (ret < 0) {
3540 cerr << "failed to init realm: " << cpp_strerror(-ret) << std::endl;
3541 return -ret;
3542 }
3543
3544 RGWZoneGroup zonegroup(zonegroup_name, is_master, g_ceph_context, store, realm.get_id(), endpoints);
3545 zonegroup.api_name = (api_name.empty() ? zonegroup_name : api_name);
3546 ret = zonegroup.create();
3547 if (ret < 0) {
3548 cerr << "failed to create zonegroup " << zonegroup_name << ": " << cpp_strerror(-ret) << std::endl;
3549 return -ret;
3550 }
3551
3552 if (set_default) {
3553 ret = zonegroup.set_as_default();
3554 if (ret < 0) {
3555 cerr << "failed to set zonegroup " << zonegroup_name << " as default: " << cpp_strerror(-ret) << std::endl;
3556 }
3557 }
3558
3559 encode_json("zonegroup", zonegroup, formatter);
3560 formatter->flush(cout);
3561 cout << std::endl;
3562 }
3563 break;
3564 case OPT_ZONEGROUP_DEFAULT:
3565 {
3566 if (zonegroup_id.empty() && zonegroup_name.empty()) {
3567 cerr << "no zonegroup name or id provided" << std::endl;
3568 return EINVAL;
3569 }
3570
3571 RGWZoneGroup zonegroup(zonegroup_id, zonegroup_name);
3572 int ret = zonegroup.init(g_ceph_context, store);
3573 if (ret < 0) {
3574 cerr << "failed to init zonegroup: " << cpp_strerror(-ret) << std::endl;
3575 return -ret;
3576 }
3577
3578 ret = zonegroup.set_as_default();
3579 if (ret < 0) {
3580 cerr << "failed to set zonegroup as default: " << cpp_strerror(-ret) << std::endl;
3581 return -ret;
3582 }
3583 }
3584 break;
3585 case OPT_ZONEGROUP_DELETE:
3586 {
3587 if (zonegroup_id.empty() && zonegroup_name.empty()) {
3588 cerr << "no zonegroup name or id provided" << std::endl;
3589 return EINVAL;
3590 }
3591 RGWZoneGroup zonegroup(zonegroup_id, zonegroup_name);
3592 int ret = zonegroup.init(g_ceph_context, store);
3593 if (ret < 0) {
3594 cerr << "failed to init zonegroup: " << cpp_strerror(-ret) << std::endl;
3595 return -ret;
3596 }
3597 ret = zonegroup.delete_obj();
3598 if (ret < 0) {
3599 cerr << "ERROR: couldn't delete zonegroup: " << cpp_strerror(-ret) << std::endl;
3600 return -ret;
3601 }
3602 }
3603 break;
3604 case OPT_ZONEGROUP_GET:
3605 {
3606 RGWZoneGroup zonegroup(zonegroup_id, zonegroup_name);
3607 int ret = zonegroup.init(g_ceph_context, store);
3608 if (ret < 0) {
3609 cerr << "failed to init zonegroup: " << cpp_strerror(-ret) << std::endl;
3610 return -ret;
3611 }
3612
3613 encode_json("zonegroup", zonegroup, formatter);
3614 formatter->flush(cout);
3615 cout << std::endl;
3616 }
3617 break;
3618 case OPT_ZONEGROUP_LIST:
3619 {
3620 RGWZoneGroup zonegroup;
3621 int ret = zonegroup.init(g_ceph_context, store, false);
3622 if (ret < 0) {
3623 cerr << "failed to init zonegroup: " << cpp_strerror(-ret) << std::endl;
3624 return -ret;
3625 }
3626
3627 list<string> zonegroups;
3628 ret = store->list_zonegroups(zonegroups);
3629 if (ret < 0) {
3630 cerr << "failed to list zonegroups: " << cpp_strerror(-ret) << std::endl;
3631 return -ret;
3632 }
3633 string default_zonegroup;
3634 ret = zonegroup.read_default_id(default_zonegroup);
3635 cout << "read_default_id : " << ret << std::endl;
3636 if (ret < 0 && ret != -ENOENT) {
3637 cerr << "could not determine default zonegroup: " << cpp_strerror(-ret) << std::endl;
3638 }
3639 formatter->open_object_section("zonegroups_list");
3640 encode_json("default_info", default_zonegroup, formatter);
3641 encode_json("zonegroups", zonegroups, formatter);
3642 formatter->close_section();
3643 formatter->flush(cout);
3644 cout << std::endl;
3645 }
3646 break;
3647 case OPT_ZONEGROUP_MODIFY:
3648 {
3649 RGWRealm realm(realm_id, realm_name);
3650 int ret = realm.init(g_ceph_context, store);
3651 if (ret < 0) {
3652 cerr << "failed to init realm: " << cpp_strerror(-ret) << std::endl;
3653 return -ret;
3654 }
3655
3656 RGWZoneGroup zonegroup(zonegroup_id, zonegroup_name);
3657 ret = zonegroup.init(g_ceph_context, store);
3658 if (ret < 0) {
3659 cerr << "failed to init zonegroup: " << cpp_strerror(-ret) << std::endl;
3660 return -ret;
3661 }
3662
3663 bool need_update = false;
3664
3665 if (!master_zone.empty()) {
3666 zonegroup.master_zone = master_zone;
3667 need_update = true;
3668 }
3669
3670 if (is_master_set) {
3671 zonegroup.update_master(is_master);
3672 need_update = true;
3673 }
3674
3675 if (!endpoints.empty()) {
3676 zonegroup.endpoints = endpoints;
3677 need_update = true;
3678 }
3679
3680 if (!api_name.empty()) {
3681 zonegroup.api_name = api_name;
3682 need_update = true;
3683 }
3684
3685 if (!realm_id.empty()) {
3686 zonegroup.realm_id = realm_id;
3687 need_update = true;
3688 } else if (!realm_name.empty()) {
3689 // get realm id from name
3690 RGWRealm realm{g_ceph_context, store};
3691 ret = realm.read_id(realm_name, zonegroup.realm_id);
3692 if (ret < 0) {
3693 cerr << "failed to find realm by name " << realm_name << std::endl;
3694 return -ret;
3695 }
3696 need_update = true;
3697 }
3698
3699 if (need_update) {
3700 ret = zonegroup.update();
3701 if (ret < 0) {
3702 cerr << "failed to update zonegroup: " << cpp_strerror(-ret) << std::endl;
3703 return -ret;
3704 }
3705 }
3706
3707 if (set_default) {
3708 ret = zonegroup.set_as_default();
3709 if (ret < 0) {
3710 cerr << "failed to set zonegroup " << zonegroup_name << " as default: " << cpp_strerror(-ret) << std::endl;
3711 }
3712 }
3713
3714 encode_json("zonegroup", zonegroup, formatter);
3715 formatter->flush(cout);
3716 }
3717 break;
3718 case OPT_ZONEGROUP_SET:
3719 {
3720 RGWRealm realm(realm_id, realm_name);
3721 int ret = realm.init(g_ceph_context, store);
3722 if (ret < 0) {
3723 cerr << "failed to init realm: " << cpp_strerror(-ret) << std::endl;
3724 return -ret;
3725 }
3726
3727 RGWZoneGroup zonegroup;
3728 ret = zonegroup.init(g_ceph_context, store, false);
3729 if (ret < 0) {
3730 cerr << "failed to init zonegroup: " << cpp_strerror(-ret) << std::endl;
3731 return -ret;
3732 }
3733 ret = read_decode_json(infile, zonegroup);
3734 if (ret < 0) {
3735 return 1;
3736 }
3737 if (zonegroup.realm_id.empty()) {
3738 zonegroup.realm_id = realm.get_id();
3739 }
3740 ret = zonegroup.create();
3741 if (ret < 0 && ret != -EEXIST) {
3742 cerr << "ERROR: couldn't create zonegroup info: " << cpp_strerror(-ret) << std::endl;
3743 return 1;
3744 } else if (ret == -EEXIST) {
3745 ret = zonegroup.update();
3746 if (ret < 0) {
3747 cerr << "ERROR: couldn't store zonegroup info: " << cpp_strerror(-ret) << std::endl;
3748 return 1;
3749 }
3750 }
3751
3752 if (set_default) {
3753 ret = zonegroup.set_as_default();
3754 if (ret < 0) {
3755 cerr << "failed to set zonegroup " << zonegroup_name << " as default: " << cpp_strerror(-ret) << std::endl;
3756 }
3757 }
3758
3759 encode_json("zonegroup", zonegroup, formatter);
3760 formatter->flush(cout);
3761 }
3762 break;
3763 case OPT_ZONEGROUP_REMOVE:
3764 {
3765 RGWZoneGroup zonegroup(zonegroup_id, zonegroup_name);
3766 int ret = zonegroup.init(g_ceph_context, store);
3767 if (ret < 0) {
3768 cerr << "failed to init zonegroup: " << cpp_strerror(-ret) << std::endl;
3769 return -ret;
3770 }
3771
3772 if (zone_id.empty()) {
3773 if (zone_name.empty()) {
3774 cerr << "no --zone-id or --rgw-zone name provided" << std::endl;
3775 return EINVAL;
3776 }
3777 // look up zone id by name
3778 for (auto& z : zonegroup.zones) {
3779 if (zone_name == z.second.name) {
3780 zone_id = z.second.id;
3781 break;
3782 }
3783 }
3784 if (zone_id.empty()) {
3785 cerr << "zone name " << zone_name << " not found in zonegroup "
3786 << zonegroup.get_name() << std::endl;
3787 return ENOENT;
3788 }
3789 }
3790
3791 ret = zonegroup.remove_zone(zone_id);
3792 if (ret < 0) {
3793 cerr << "failed to remove zone: " << cpp_strerror(-ret) << std::endl;
3794 return -ret;
3795 }
3796
3797 encode_json("zonegroup", zonegroup, formatter);
3798 formatter->flush(cout);
3799 }
3800 break;
3801 case OPT_ZONEGROUP_RENAME:
3802 {
3803 if (zonegroup_new_name.empty()) {
3804 cerr << " missing zonegroup new name" << std::endl;
3805 return EINVAL;
3806 }
3807 if (zonegroup_id.empty() && zonegroup_name.empty()) {
3808 cerr << "no zonegroup name or id provided" << std::endl;
3809 return EINVAL;
3810 }
3811 RGWZoneGroup zonegroup(zonegroup_id, zonegroup_name);
3812 int ret = zonegroup.init(g_ceph_context, store);
3813 if (ret < 0) {
3814 cerr << "failed to init zonegroup: " << cpp_strerror(-ret) << std::endl;
3815 return -ret;
3816 }
3817 ret = zonegroup.rename(zonegroup_new_name);
3818 if (ret < 0) {
3819 cerr << "failed to rename zonegroup: " << cpp_strerror(-ret) << std::endl;
3820 return -ret;
3821 }
3822 }
3823 break;
3824 case OPT_ZONEGROUP_PLACEMENT_LIST:
3825 {
3826 RGWZoneGroup zonegroup(zonegroup_id, zonegroup_name);
3827 int ret = zonegroup.init(g_ceph_context, store);
3828 if (ret < 0) {
3829 cerr << "failed to init zonegroup: " << cpp_strerror(-ret) << std::endl;
3830 return -ret;
3831 }
3832
3833 encode_json("placement_targets", zonegroup.placement_targets, formatter);
3834 formatter->flush(cout);
3835 cout << std::endl;
3836 }
3837 break;
3838 case OPT_ZONEGROUP_PLACEMENT_ADD:
3839 case OPT_ZONEGROUP_PLACEMENT_MODIFY:
3840 case OPT_ZONEGROUP_PLACEMENT_RM:
3841 case OPT_ZONEGROUP_PLACEMENT_DEFAULT:
3842 {
3843 if (placement_id.empty()) {
3844 cerr << "ERROR: --placement-id not specified" << std::endl;
3845 return EINVAL;
3846 }
3847
3848 RGWZoneGroup zonegroup(zonegroup_id, zonegroup_name);
3849 int ret = zonegroup.init(g_ceph_context, store);
3850 if (ret < 0) {
3851 cerr << "failed to init zonegroup: " << cpp_strerror(-ret) << std::endl;
3852 return -ret;
3853 }
3854
3855 if (opt_cmd == OPT_ZONEGROUP_PLACEMENT_ADD) {
3856 RGWZoneGroupPlacementTarget target;
3857 target.name = placement_id;
3858 for (auto& t : tags) {
3859 target.tags.insert(t);
3860 }
3861 zonegroup.placement_targets[placement_id] = target;
3862 } else if (opt_cmd == OPT_ZONEGROUP_PLACEMENT_MODIFY) {
3863 RGWZoneGroupPlacementTarget& target = zonegroup.placement_targets[placement_id];
3864 if (!tags.empty()) {
3865 target.tags.clear();
3866 for (auto& t : tags) {
3867 target.tags.insert(t);
3868 }
3869 }
3870 target.name = placement_id;
3871 for (auto& t : tags_rm) {
3872 target.tags.erase(t);
3873 }
3874 for (auto& t : tags_add) {
3875 target.tags.insert(t);
3876 }
3877 } else if (opt_cmd == OPT_ZONEGROUP_PLACEMENT_RM) {
3878 zonegroup.placement_targets.erase(placement_id);
3879 } else if (opt_cmd == OPT_ZONEGROUP_PLACEMENT_DEFAULT) {
3880 if (!zonegroup.placement_targets.count(placement_id)) {
3881 cerr << "failed to find a zonegroup placement target named '"
3882 << placement_id << "'" << std::endl;
3883 return -ENOENT;
3884 }
3885 zonegroup.default_placement = placement_id;
3886 }
3887
3888 zonegroup.post_process_params();
3889 ret = zonegroup.update();
3890 if (ret < 0) {
3891 cerr << "failed to update zonegroup: " << cpp_strerror(-ret) << std::endl;
3892 return -ret;
3893 }
3894
3895 encode_json("placement_targets", zonegroup.placement_targets, formatter);
3896 formatter->flush(cout);
3897 }
3898 break;
3899 case OPT_ZONE_CREATE:
3900 {
3901 if (zone_name.empty()) {
3902 cerr << "zone name not provided" << std::endl;
3903 return EINVAL;
3904 }
3905 int ret;
3906 RGWZoneGroup zonegroup(zonegroup_id, zonegroup_name);
3907 /* if the user didn't provide zonegroup info , create stand alone zone */
3908 if (!zonegroup_id.empty() || !zonegroup_name.empty()) {
3909 ret = zonegroup.init(g_ceph_context, store);
3910 if (ret < 0) {
3911 cerr << "unable to initialize zonegroup " << zonegroup_name << ": " << cpp_strerror(-ret) << std::endl;
3912 return -ret;
3913 }
3914 if (realm_id.empty() && realm_name.empty()) {
3915 realm_id = zonegroup.realm_id;
3916 }
3917 }
3918
3919 RGWZoneParams zone(zone_id, zone_name);
3920 ret = zone.init(g_ceph_context, store, false);
3921 if (ret < 0) {
3922 cerr << "unable to initialize zone: " << cpp_strerror(-ret) << std::endl;
3923 return -ret;
3924 }
3925
3926 zone.system_key.id = access_key;
3927 zone.system_key.key = secret_key;
3928 zone.realm_id = realm_id;
3929
3930 ret = zone.create();
3931 if (ret < 0) {
3932 cerr << "failed to create zone " << zone_name << ": " << cpp_strerror(-ret) << std::endl;
3933 return -ret;
3934 }
3935
3936 if (!zonegroup_id.empty() || !zonegroup_name.empty()) {
3937 string *ptier_type = (tier_type_specified ? &tier_type : nullptr);
3938 bool *psync_from_all = (sync_from_all_specified ? &sync_from_all : nullptr);
3939 ret = zonegroup.add_zone(zone,
3940 (is_master_set ? &is_master : NULL),
3941 (is_read_only_set ? &read_only : NULL),
3942 endpoints,
3943 ptier_type,
3944 psync_from_all,
3945 sync_from, sync_from_rm);
3946 if (ret < 0) {
3947 cerr << "failed to add zone " << zone_name << " to zonegroup " << zonegroup.get_name()
3948 << ": " << cpp_strerror(-ret) << std::endl;
3949 return -ret;
3950 }
3951 }
3952
3953 if (set_default) {
3954 ret = zone.set_as_default();
3955 if (ret < 0) {
3956 cerr << "failed to set zone " << zone_name << " as default: " << cpp_strerror(-ret) << std::endl;
3957 }
3958 }
3959
3960 encode_json("zone", zone, formatter);
3961 formatter->flush(cout);
3962 cout << std::endl;
3963 }
3964 break;
3965 case OPT_ZONE_DEFAULT:
3966 {
3967 RGWZoneGroup zonegroup(zonegroup_id,zonegroup_name);
3968 int ret = zonegroup.init(g_ceph_context, store);
3969 if (ret < 0) {
3970 cerr << "WARNING: failed to initialize zonegroup " << zonegroup_name << std::endl;
3971 }
3972 if (zone_id.empty() && zone_name.empty()) {
3973 cerr << "no zone name or id provided" << std::endl;
3974 return EINVAL;
3975 }
3976 RGWZoneParams zone(zone_id, zone_name);
3977 ret = zone.init(g_ceph_context, store);
3978 if (ret < 0) {
3979 cerr << "unable to initialize zone: " << cpp_strerror(-ret) << std::endl;
3980 return -ret;
3981 }
3982 ret = zone.set_as_default();
3983 if (ret < 0) {
3984 cerr << "failed to set zone as default: " << cpp_strerror(-ret) << std::endl;
3985 return -ret;
3986 }
3987 }
3988 break;
3989 case OPT_ZONE_DELETE:
3990 {
3991 if (zone_id.empty() && zone_name.empty()) {
3992 cerr << "no zone name or id provided" << std::endl;
3993 return EINVAL;
3994 }
3995 RGWZoneParams zone(zone_id, zone_name);
3996 int ret = zone.init(g_ceph_context, store);
3997 if (ret < 0) {
3998 cerr << "unable to initialize zone: " << cpp_strerror(-ret) << std::endl;
3999 return -ret;
4000 }
4001
4002 list<string> zonegroups;
4003 ret = store->list_zonegroups(zonegroups);
4004 if (ret < 0) {
4005 cerr << "failed to list zonegroups: " << cpp_strerror(-ret) << std::endl;
4006 return -ret;
4007 }
4008
4009 for (list<string>::iterator iter = zonegroups.begin(); iter != zonegroups.end(); ++iter) {
4010 RGWZoneGroup zonegroup(string(), *iter);
4011 int ret = zonegroup.init(g_ceph_context, store);
4012 if (ret < 0) {
4013 cerr << "WARNING: failed to initialize zonegroup " << zonegroup_name << std::endl;
4014 continue;
4015 }
4016 ret = zonegroup.remove_zone(zone.get_id());
4017 if (ret < 0 && ret != -ENOENT) {
4018 cerr << "failed to remove zone " << zone_name << " from zonegroup " << zonegroup.get_name() << ": "
4019 << cpp_strerror(-ret) << std::endl;
4020 }
4021 }
4022
4023 ret = zone.delete_obj();
4024 if (ret < 0) {
4025 cerr << "failed to delete zone " << zone_name << ": " << cpp_strerror(-ret) << std::endl;
4026 return -ret;
4027 }
4028 }
4029 break;
4030 case OPT_ZONE_GET:
4031 {
4032 RGWZoneParams zone(zone_id, zone_name);
4033 int ret = zone.init(g_ceph_context, store);
4034 if (ret < 0) {
4035 cerr << "unable to initialize zone: " << cpp_strerror(-ret) << std::endl;
4036 return -ret;
4037 }
4038 encode_json("zone", zone, formatter);
4039 formatter->flush(cout);
4040 }
4041 break;
4042 case OPT_ZONE_SET:
4043 {
4044 RGWZoneParams zone(zone_name);
4045 int ret = zone.init(g_ceph_context, store, false);
4046 if (ret < 0) {
4047 return -ret;
4048 }
4049
4050 ret = zone.read();
4051 if (ret < 0 && ret != -ENOENT) {
4052 cerr << "zone.read() returned ret=" << ret << std::endl;
4053 return -ret;
4054 }
4055
4056 string orig_id = zone.get_id();
4057
4058 ret = read_decode_json(infile, zone);
4059 if (ret < 0) {
4060 return 1;
4061 }
4062
4063 if(zone.realm_id.empty()) {
4064 RGWRealm realm(realm_id, realm_name);
4065 int ret = realm.init(g_ceph_context, store);
4066 if (ret < 0 && ret != -ENOENT) {
4067 cerr << "failed to init realm: " << cpp_strerror(-ret) << std::endl;
4068 return -ret;
4069 }
4070 zone.realm_id = realm.get_id();
4071 }
4072
4073 if( !zone_name.empty() && !zone.get_name().empty() && zone.get_name() != zone_name) {
4074 cerr << "Error: zone name" << zone_name << " is different than the zone name " << zone.get_name() << " in the provided json " << std::endl;
4075 return EINVAL;
4076 }
4077
4078 if (zone.get_name().empty()) {
4079 zone.set_name(zone_name);
4080 if (zone.get_name().empty()) {
4081 cerr << "no zone name specified" << std::endl;
4082 return EINVAL;
4083 }
4084 }
4085
4086 zone_name = zone.get_name();
4087
4088 if (zone.get_id().empty()) {
4089 zone.set_id(orig_id);
4090 }
4091
4092 if (zone.get_id().empty()) {
4093 cerr << "no zone name id the json provided, assuming old format" << std::endl;
4094 if (zone_name.empty()) {
4095 cerr << "missing zone name" << std::endl;
4096 return EINVAL;
4097 }
4098 zone.set_name(zone_name);
4099 zone.set_id(zone_name);
4100 }
4101
4102 cerr << "zone id " << zone.get_id();
4103 ret = zone.fix_pool_names();
4104 if (ret < 0) {
4105 cerr << "ERROR: couldn't fix zone: " << cpp_strerror(-ret) << std::endl;
4106 return -ret;
4107 }
4108 ret = zone.write(false);
4109 if (ret < 0) {
4110 cerr << "ERROR: couldn't create zone: " << cpp_strerror(-ret) << std::endl;
4111 return 1;
4112 }
4113
4114 if (set_default) {
4115 ret = zone.set_as_default();
4116 if (ret < 0) {
4117 cerr << "failed to set zone " << zone_name << " as default: " << cpp_strerror(-ret) << std::endl;
4118 }
4119 }
4120
4121 encode_json("zone", zone, formatter);
4122 formatter->flush(cout);
4123 }
4124 break;
4125 case OPT_ZONE_LIST:
4126 {
4127 list<string> zones;
4128 int ret = store->list_zones(zones);
4129 if (ret < 0) {
4130 cerr << "failed to list zones: " << cpp_strerror(-ret) << std::endl;
4131 return -ret;
4132 }
4133
4134 RGWZoneParams zone;
4135 ret = zone.init(g_ceph_context, store, false);
4136 if (ret < 0) {
4137 cerr << "failed to init zone: " << cpp_strerror(-ret) << std::endl;
4138 return -ret;
4139 }
4140 string default_zone;
4141 ret = zone.read_default_id(default_zone);
4142 if (ret < 0 && ret != -ENOENT) {
4143 cerr << "could not determine default zone: " << cpp_strerror(-ret) << std::endl;
4144 }
4145 formatter->open_object_section("zones_list");
4146 encode_json("default_info", default_zone, formatter);
4147 encode_json("zones", zones, formatter);
4148 formatter->close_section();
4149 formatter->flush(cout);
4150 cout << std::endl;
4151 }
4152 break;
4153 case OPT_ZONE_MODIFY:
4154 {
4155 RGWZoneParams zone(zone_id, zone_name);
4156 int ret = zone.init(g_ceph_context, store);
4157 if (ret < 0) {
4158 cerr << "failed to init zone: " << cpp_strerror(-ret) << std::endl;
4159 return -ret;
4160 }
4161
4162 bool need_zone_update = false;
4163 if (!access_key.empty()) {
4164 zone.system_key.id = access_key;
4165 need_zone_update = true;
4166 }
4167
4168 if (!secret_key.empty()) {
4169 zone.system_key.key = secret_key;
4170 need_zone_update = true;
4171 }
4172
4173 if (!realm_id.empty()) {
4174 zone.realm_id = realm_id;
4175 need_zone_update = true;
4176 } else if (!realm_name.empty()) {
4177 // get realm id from name
4178 RGWRealm realm{g_ceph_context, store};
4179 ret = realm.read_id(realm_name, zone.realm_id);
4180 if (ret < 0) {
4181 cerr << "failed to find realm by name " << realm_name << std::endl;
4182 return -ret;
4183 }
4184 need_zone_update = true;
4185 }
4186
4187 for (auto add : tier_config_add) {
4188 zone.tier_config[add.first] = add.second;
4189 need_zone_update = true;
4190 }
4191
4192 for (auto rm : tier_config_rm) {
4193 zone.tier_config.erase(rm.first);
4194 need_zone_update = true;
4195 }
4196
4197 if (need_zone_update) {
4198 ret = zone.update();
4199 if (ret < 0) {
4200 cerr << "failed to save zone info: " << cpp_strerror(-ret) << std::endl;
4201 return -ret;
4202 }
4203 }
4204
4205 RGWZoneGroup zonegroup(zonegroup_id, zonegroup_name);
4206 ret = zonegroup.init(g_ceph_context, store);
4207 if (ret < 0) {
4208 cerr << "failed to init zonegroup: " << cpp_strerror(-ret) << std::endl;
4209 return -ret;
4210 }
4211 string *ptier_type = (tier_type_specified ? &tier_type : nullptr);
4212
4213 bool *psync_from_all = (sync_from_all_specified ? &sync_from_all : nullptr);
4214
4215 ret = zonegroup.add_zone(zone,
4216 (is_master_set ? &is_master : NULL),
4217 (is_read_only_set ? &read_only : NULL),
4218 endpoints, ptier_type,
4219 psync_from_all, sync_from, sync_from_rm);
4220 if (ret < 0) {
4221 cerr << "failed to update zonegroup: " << cpp_strerror(-ret) << std::endl;
4222 return -ret;
4223 }
4224
4225 ret = zonegroup.update();
4226 if (ret < 0) {
4227 cerr << "failed to update zonegroup: " << cpp_strerror(-ret) << std::endl;
4228 return -ret;
4229 }
4230
4231 if (set_default) {
4232 ret = zone.set_as_default();
4233 if (ret < 0) {
4234 cerr << "failed to set zone " << zone_name << " as default: " << cpp_strerror(-ret) << std::endl;
4235 }
4236 }
4237
4238 encode_json("zone", zone, formatter);
4239 formatter->flush(cout);
4240 }
4241 break;
4242 case OPT_ZONE_RENAME:
4243 {
4244 if (zone_new_name.empty()) {
4245 cerr << " missing zone new name" << std::endl;
4246 return EINVAL;
4247 }
4248 if (zone_id.empty() && zone_name.empty()) {
4249 cerr << "no zonegroup name or id provided" << std::endl;
4250 return EINVAL;
4251 }
4252 RGWZoneParams zone(zone_id,zone_name);
4253 int ret = zone.init(g_ceph_context, store);
4254 if (ret < 0) {
4255 cerr << "unable to initialize zone: " << cpp_strerror(-ret) << std::endl;
4256 return -ret;
4257 }
4258 ret = zone.rename(zone_new_name);
4259 if (ret < 0) {
4260 cerr << "failed to rename zone " << zone_name << " to " << zone_new_name << ": " << cpp_strerror(-ret)
4261 << std::endl;
4262 return -ret;
4263 }
4264 RGWZoneGroup zonegroup(zonegroup_id, zonegroup_name);
4265 ret = zonegroup.init(g_ceph_context, store);
4266 if (ret < 0) {
4267 cerr << "WARNING: failed to initialize zonegroup " << zonegroup_name << std::endl;
4268 } else {
4269 ret = zonegroup.rename_zone(zone);
4270 if (ret < 0 && ret ) {
4271 cerr << "Error in zonegroup rename for " << zone_name << ": " << cpp_strerror(-ret) << std::endl;
4272 return -ret;
4273 }
4274 }
4275 }
4276 break;
4277 case OPT_ZONE_PLACEMENT_ADD:
4278 case OPT_ZONE_PLACEMENT_MODIFY:
4279 case OPT_ZONE_PLACEMENT_RM:
4280 {
4281 if (placement_id.empty()) {
4282 cerr << "ERROR: --placement-id not specified" << std::endl;
4283 return EINVAL;
4284 }
4285 RGWZoneParams zone(zone_id, zone_name);
4286 int ret = zone.init(g_ceph_context, store);
4287 if (ret < 0) {
4288 cerr << "failed to init zone: " << cpp_strerror(-ret) << std::endl;
4289 return -ret;
4290 }
4291
4292 if (opt_cmd == OPT_ZONE_PLACEMENT_ADD) {
4293 // pool names are required
4294 if (!index_pool || index_pool->empty() ||
4295 !data_pool || data_pool->empty()) {
4296 cerr << "ERROR: need to specify both --index-pool and --data-pool" << std::endl;
4297 return EINVAL;
4298 }
4299
4300 RGWZonePlacementInfo& info = zone.placement_pools[placement_id];
4301
4302 info.index_pool = *index_pool;
4303 info.data_pool = *data_pool;
4304 if (data_extra_pool) {
4305 info.data_extra_pool = *data_extra_pool;
4306 }
4307 if (index_type_specified) {
4308 info.index_type = placement_index_type;
4309 }
4310 if (compression_type) {
4311 info.compression_type = *compression_type;
4312 }
4313 } else if (opt_cmd == OPT_ZONE_PLACEMENT_MODIFY) {
4314 auto p = zone.placement_pools.find(placement_id);
4315 if (p == zone.placement_pools.end()) {
4316 cerr << "ERROR: zone placement target '" << placement_id
4317 << "' not found" << std::endl;
4318 return -ENOENT;
4319 }
4320 auto& info = p->second;
4321 if (index_pool && !index_pool->empty()) {
4322 info.index_pool = *index_pool;
4323 }
4324 if (data_pool && !data_pool->empty()) {
4325 info.data_pool = *data_pool;
4326 }
4327 if (data_extra_pool) {
4328 info.data_extra_pool = *data_extra_pool;
4329 }
4330 if (index_type_specified) {
4331 info.index_type = placement_index_type;
4332 }
4333 if (compression_type) {
4334 info.compression_type = *compression_type;
4335 }
4336 } else if (opt_cmd == OPT_ZONE_PLACEMENT_RM) {
4337 zone.placement_pools.erase(placement_id);
4338 }
4339
4340 ret = zone.update();
4341 if (ret < 0) {
4342 cerr << "failed to save zone info: " << cpp_strerror(-ret) << std::endl;
4343 return -ret;
4344 }
4345
4346 encode_json("zone", zone, formatter);
4347 formatter->flush(cout);
4348 }
4349 break;
4350 case OPT_ZONE_PLACEMENT_LIST:
4351 {
4352 RGWZoneParams zone(zone_id, zone_name);
4353 int ret = zone.init(g_ceph_context, store);
4354 if (ret < 0) {
4355 cerr << "unable to initialize zone: " << cpp_strerror(-ret) << std::endl;
4356 return -ret;
4357 }
4358 encode_json("placement_pools", zone.placement_pools, formatter);
4359 formatter->flush(cout);
4360 }
4361 break;
4362 }
4363 return 0;
4364 }
4365
4366 if (!user_id.empty()) {
4367 user_op.set_user_id(user_id);
4368 bucket_op.set_user_id(user_id);
4369 }
4370
4371 if (!display_name.empty())
4372 user_op.set_display_name(display_name);
4373
4374 if (!user_email.empty())
4375 user_op.set_user_email(user_email);
4376
4377 if (!access_key.empty())
4378 user_op.set_access_key(access_key);
4379
4380 if (!secret_key.empty())
4381 user_op.set_secret_key(secret_key);
4382
4383 if (!subuser.empty())
4384 user_op.set_subuser(subuser);
4385
4386 if (!caps.empty())
4387 user_op.set_caps(caps);
4388
4389 user_op.set_purge_data(purge_data);
4390
4391 if (purge_keys)
4392 user_op.set_purge_keys();
4393
4394 if (gen_access_key)
4395 user_op.set_generate_key();
4396
4397 if (gen_secret_key)
4398 user_op.set_gen_secret(); // assume that a key pair should be created
4399
4400 if (max_buckets_specified)
4401 user_op.set_max_buckets(max_buckets);
4402
4403 if (admin_specified)
4404 user_op.set_admin(admin);
4405
4406 if (system_specified)
4407 user_op.set_system(system);
4408
4409 if (set_perm)
4410 user_op.set_perm(perm_mask);
4411
4412 if (set_temp_url_key) {
4413 map<int, string>::iterator iter = temp_url_keys.begin();
4414 for (; iter != temp_url_keys.end(); ++iter) {
4415 user_op.set_temp_url_key(iter->second, iter->first);
4416 }
4417 }
4418
4419 if (!op_mask_str.empty()) {
4420 uint32_t op_mask;
4421 int ret = rgw_parse_op_type_list(op_mask_str, &op_mask);
4422 if (ret < 0) {
4423 cerr << "failed to parse op_mask: " << cpp_strerror(-ret) << std::endl;
4424 return -ret;
4425 }
4426
4427 user_op.set_op_mask(op_mask);
4428 }
4429
4430 if (key_type != KEY_TYPE_UNDEFINED)
4431 user_op.set_key_type(key_type);
4432
4433 // set suspension operation parameters
4434 if (opt_cmd == OPT_USER_ENABLE)
4435 user_op.set_suspension(false);
4436 else if (opt_cmd == OPT_USER_SUSPEND)
4437 user_op.set_suspension(true);
4438
4439 // RGWUser to use for user operations
4440 RGWUser user;
4441 int ret = 0;
4442 if (!user_id.empty() || !subuser.empty()) {
4443 ret = user.init(store, user_op);
4444 if (ret < 0) {
4445 cerr << "user.init failed: " << cpp_strerror(-ret) << std::endl;
4446 return -ret;
4447 }
4448 }
4449
4450 /* populate bucket operation */
4451 bucket_op.set_bucket_name(bucket_name);
4452 bucket_op.set_object(object);
4453 bucket_op.set_check_objects(check_objects);
4454 bucket_op.set_delete_children(delete_child_objects);
4455 bucket_op.set_fix_index(fix);
4456 bucket_op.set_max_aio(max_concurrent_ios);
4457
4458 // required to gather errors from operations
4459 std::string err_msg;
4460
4461 bool output_user_info = true;
4462
4463 switch (opt_cmd) {
4464 case OPT_USER_INFO:
4465 break;
4466 case OPT_USER_CREATE:
4467 if (!user_op.has_existing_user()) {
4468 user_op.set_generate_key(); // generate a new key by default
4469 }
4470 ret = user.add(user_op, &err_msg);
4471 if (ret < 0) {
4472 cerr << "could not create user: " << err_msg << std::endl;
4473 return -ret;
4474 }
4475 if (!subuser.empty()) {
4476 ret = user.subusers.add(user_op, &err_msg);
4477 if (ret < 0) {
4478 cerr << "could not create subuser: " << err_msg << std::endl;
4479 return -ret;
4480 }
4481 }
4482 break;
4483 case OPT_USER_RM:
4484 ret = user.remove(user_op, &err_msg);
4485 if (ret == -ENOENT) {
4486 cerr << err_msg << std::endl;
4487 } else if (ret < 0) {
4488 cerr << "could not remove user: " << err_msg << std::endl;
4489 return -ret;
4490 }
4491
4492 output_user_info = false;
4493 break;
4494 case OPT_USER_ENABLE:
4495 case OPT_USER_SUSPEND:
4496 case OPT_USER_MODIFY:
4497 ret = user.modify(user_op, &err_msg);
4498 if (ret < 0) {
4499 cerr << "could not modify user: " << err_msg << std::endl;
4500 return -ret;
4501 }
4502
4503 break;
4504 case OPT_SUBUSER_CREATE:
4505 ret = user.subusers.add(user_op, &err_msg);
4506 if (ret < 0) {
4507 cerr << "could not create subuser: " << err_msg << std::endl;
4508 return -ret;
4509 }
4510
4511 break;
4512 case OPT_SUBUSER_MODIFY:
4513 ret = user.subusers.modify(user_op, &err_msg);
4514 if (ret < 0) {
4515 cerr << "could not modify subuser: " << err_msg << std::endl;
4516 return -ret;
4517 }
4518
4519 break;
4520 case OPT_SUBUSER_RM:
4521 ret = user.subusers.remove(user_op, &err_msg);
4522 if (ret < 0) {
4523 cerr << "could not remove subuser: " << err_msg << std::endl;
4524 return -ret;
4525 }
4526
4527 break;
4528 case OPT_CAPS_ADD:
4529 ret = user.caps.add(user_op, &err_msg);
4530 if (ret < 0) {
4531 cerr << "could not add caps: " << err_msg << std::endl;
4532 return -ret;
4533 }
4534
4535 break;
4536 case OPT_CAPS_RM:
4537 ret = user.caps.remove(user_op, &err_msg);
4538 if (ret < 0) {
4539 cerr << "could not remove caps: " << err_msg << std::endl;
4540 return -ret;
4541 }
4542
4543 break;
4544 case OPT_KEY_CREATE:
4545 ret = user.keys.add(user_op, &err_msg);
4546 if (ret < 0) {
4547 cerr << "could not create key: " << err_msg << std::endl;
4548 return -ret;
4549 }
4550
4551 break;
4552 case OPT_KEY_RM:
4553 ret = user.keys.remove(user_op, &err_msg);
4554 if (ret < 0) {
4555 cerr << "could not remove key: " << err_msg << std::endl;
4556 return -ret;
4557 }
4558 break;
4559 case OPT_PERIOD_PUSH:
4560 {
4561 RGWEnv env;
4562 req_info info(g_ceph_context, &env);
4563 info.method = "POST";
4564 info.request_uri = "/admin/realm/period";
4565
4566 map<string, string> &params = info.args.get_params();
4567 if (!realm_id.empty())
4568 params["realm_id"] = realm_id;
4569 if (!realm_name.empty())
4570 params["realm_name"] = realm_name;
4571 if (!period_id.empty())
4572 params["period_id"] = period_id;
4573 if (!period_epoch.empty())
4574 params["epoch"] = period_epoch;
4575
4576 // load the period
4577 RGWPeriod period(period_id);
4578 int ret = period.init(g_ceph_context, store);
4579 if (ret < 0) {
4580 cerr << "period init failed: " << cpp_strerror(-ret) << std::endl;
4581 return -ret;
4582 }
4583 // json format into a bufferlist
4584 JSONFormatter jf(false);
4585 encode_json("period", period, &jf);
4586 bufferlist bl;
4587 jf.flush(bl);
4588
4589 JSONParser p;
4590 ret = send_to_remote_or_url(nullptr, url, access_key, secret_key,
4591 info, bl, p);
4592 if (ret < 0) {
4593 cerr << "request failed: " << cpp_strerror(-ret) << std::endl;
4594 return -ret;
4595 }
4596 }
4597 return 0;
4598 case OPT_PERIOD_UPDATE:
4599 {
4600 int ret = update_period(realm_id, realm_name, period_id, period_epoch,
4601 commit, remote, url, access_key, secret_key,
4602 formatter, yes_i_really_mean_it);
4603 if (ret < 0) {
4604 return -ret;
4605 }
4606 }
4607 return 0;
4608 case OPT_PERIOD_COMMIT:
4609 {
4610 // read realm and staging period
4611 RGWRealm realm(realm_id, realm_name);
4612 int ret = realm.init(g_ceph_context, store);
4613 if (ret < 0) {
4614 cerr << "Error initializing realm: " << cpp_strerror(-ret) << std::endl;
4615 return -ret;
4616 }
4617 RGWPeriod period(RGWPeriod::get_staging_id(realm.get_id()), 1);
4618 ret = period.init(g_ceph_context, store, realm.get_id());
4619 if (ret < 0) {
4620 cerr << "period init failed: " << cpp_strerror(-ret) << std::endl;
4621 return -ret;
4622 }
4623 ret = commit_period(realm, period, remote, url, access_key, secret_key,
4624 yes_i_really_mean_it);
4625 if (ret < 0) {
4626 cerr << "failed to commit period: " << cpp_strerror(-ret) << std::endl;
4627 return -ret;
4628 }
4629
4630 encode_json("period", period, formatter);
4631 formatter->flush(cout);
4632 cout << std::endl;
4633 }
4634 return 0;
4635 case OPT_ROLE_CREATE:
4636 {
4637 string uid;
4638 user_id.to_str(uid);
4639 if (role_name.empty() || assume_role_doc.empty() || uid.empty()) {
4640 cerr << "ERROR: one of role name or assume role policy document or uid is empty" << std::endl;
4641 return -EINVAL;
4642 }
4643 /* The following two calls will be replaced by read_decode_json or something
4644 similar when the code for AWS Policies is in places */
4645 bufferlist bl;
4646 int ret = read_input(assume_role_doc, bl);
4647 if (ret < 0) {
4648 cerr << "ERROR: failed to read input: " << cpp_strerror(-ret) << std::endl;
4649 return ret;
4650 }
4651 JSONParser p;
4652 if (!p.parse(bl.c_str(), bl.length())) {
4653 cout << "ERROR: failed to parse JSON: " << assume_role_doc << std::endl;
4654 return -EINVAL;
4655 }
4656 string trust_policy = bl.to_str();
4657 RGWRole role(g_ceph_context, store, role_name, path, trust_policy, uid);
4658 ret = role.create(true);
4659 if (ret < 0) {
4660 return -ret;
4661 }
4662 show_role_info(role, formatter);
4663 return 0;
4664 }
4665 case OPT_ROLE_DELETE:
4666 {
4667 if (role_name.empty()) {
4668 cerr << "ERROR: empty role name" << std::endl;
4669 return -EINVAL;
4670 }
4671 RGWRole role(g_ceph_context, store, role_name);
4672 ret = role.delete_obj();
4673 if (ret < 0) {
4674 return -ret;
4675 }
4676 cout << "role: " << role_name << " successfully deleted" << std::endl;
4677 return 0;
4678 }
4679 case OPT_ROLE_GET:
4680 {
4681 if (role_name.empty()) {
4682 cerr << "ERROR: empty role name" << std::endl;
4683 return -EINVAL;
4684 }
4685 RGWRole role(g_ceph_context, store, role_name);
4686 ret = role.get();
4687 if (ret < 0) {
4688 return -ret;
4689 }
4690 show_role_info(role, formatter);
4691 return 0;
4692 }
4693 case OPT_ROLE_MODIFY:
4694 {
4695 if (role_name.empty() || assume_role_doc.empty()) {
4696 cerr << "ERROR: one of role name or assume role policy document is empty" << std::endl;
4697 return -EINVAL;
4698 }
4699 /* The following two calls will be replaced by read_decode_json or something
4700 similar when the code for AWS Policies is in place */
4701 bufferlist bl;
4702 int ret = read_input(assume_role_doc, bl);
4703 if (ret < 0) {
4704 cerr << "ERROR: failed to read input: " << cpp_strerror(-ret) << std::endl;
4705 return ret;
4706 }
4707 JSONParser p;
4708 if (!p.parse(bl.c_str(), bl.length())) {
4709 cout << "ERROR: failed to parse JSON: " << assume_role_doc << std::endl;
4710 return -EINVAL;
4711 }
4712 string trust_policy = bl.to_str();
4713 RGWRole role(g_ceph_context, store, role_name);
4714 ret = role.get();
4715 if (ret < 0) {
4716 return -ret;
4717 }
4718 role.update_trust_policy(trust_policy);
4719 ret = role.update();
4720 if (ret < 0) {
4721 return -ret;
4722 }
4723 cout << "Assume role policy document updated successfully for role: " << role_name << std::endl;
4724 return 0;
4725 }
4726 case OPT_ROLE_LIST:
4727 {
4728 vector<RGWRole> result;
4729 ret = RGWRole::get_roles_by_path_prefix(store, g_ceph_context, path_prefix, result);
4730 if (ret < 0) {
4731 return -ret;
4732 }
4733 show_roles_info(result, formatter);
4734 return 0;
4735 }
4736 case OPT_ROLE_POLICY_PUT:
4737 {
4738 if (role_name.empty() || policy_name.empty() || perm_policy_doc.empty()) {
4739 cerr << "One of role name, policy name or permission policy document is empty" << std::endl;
4740 return -EINVAL;
4741 }
4742 /* The following two calls will be replaced by read_decode_json or something
4743 similar, when code for AWS Policies is in place.*/
4744 bufferlist bl;
4745 int ret = read_input(perm_policy_doc, bl);
4746 if (ret < 0) {
4747 cerr << "ERROR: failed to read input: " << cpp_strerror(-ret) << std::endl;
4748 return ret;
4749 }
4750 JSONParser p;
4751 if (!p.parse(bl.c_str(), bl.length())) {
4752 cout << "ERROR: failed to parse JSON: " << std::endl;
4753 return -EINVAL;
4754 }
4755 string perm_policy;
4756 perm_policy = bl.c_str();
4757
4758 RGWRole role(g_ceph_context, store, role_name);
4759 ret = role.get();
4760 if (ret < 0) {
4761 return -ret;
4762 }
4763 role.set_perm_policy(policy_name, perm_policy);
4764 ret = role.update();
4765 if (ret < 0) {
4766 return -ret;
4767 }
4768 cout << "Permission policy attached successfully" << std::endl;
4769 return 0;
4770 }
4771 case OPT_ROLE_POLICY_LIST:
4772 {
4773 if (role_name.empty()) {
4774 cerr << "ERROR: Role name is empty" << std::endl;
4775 return -EINVAL;
4776 }
4777 RGWRole role(g_ceph_context, store, role_name);
4778 ret = role.get();
4779 if (ret < 0) {
4780 return -ret;
4781 }
4782 std::vector<string> policy_names = role.get_role_policy_names();
4783 show_policy_names(policy_names, formatter);
4784 return 0;
4785 }
4786 case OPT_ROLE_POLICY_GET:
4787 {
4788 if (role_name.empty() || policy_name.empty()) {
4789 cerr << "ERROR: One of role name or policy name is empty" << std::endl;
4790 return -EINVAL;
4791 }
4792 RGWRole role(g_ceph_context, store, role_name);
4793 int ret = role.get();
4794 if (ret < 0) {
4795 return -ret;
4796 }
4797 string perm_policy;
4798 ret = role.get_role_policy(policy_name, perm_policy);
4799 if (ret < 0) {
4800 return -ret;
4801 }
4802 show_perm_policy(perm_policy, formatter);
4803 return 0;
4804 }
4805 case OPT_ROLE_POLICY_DELETE:
4806 {
4807 if (role_name.empty() || policy_name.empty()) {
4808 cerr << "ERROR: One of role name or policy name is empty" << std::endl;
4809 return -EINVAL;
4810 }
4811 RGWRole role(g_ceph_context, store, role_name);
4812 ret = role.get();
4813 if (ret < 0) {
4814 return -ret;
4815 }
4816 ret = role.delete_policy(policy_name);
4817 if (ret < 0) {
4818 return -ret;
4819 }
4820 ret = role.update();
4821 if (ret < 0) {
4822 return -ret;
4823 }
4824 cout << "Policy: " << policy_name << " successfully deleted for role: "
4825 << role_name << std::endl;
4826 return 0;
4827 }
4828 default:
4829 output_user_info = false;
4830 }
4831
4832 // output the result of a user operation
4833 if (output_user_info) {
4834 ret = user.info(info, &err_msg);
4835 if (ret < 0) {
4836 cerr << "could not fetch user info: " << err_msg << std::endl;
4837 return -ret;
4838 }
4839 show_user_info(info, formatter);
4840 }
4841
4842 if (opt_cmd == OPT_POLICY) {
4843 if (format == "xml") {
4844 int ret = RGWBucketAdminOp::dump_s3_policy(store, bucket_op, cout);
4845 if (ret < 0) {
4846 cerr << "ERROR: failed to get policy: " << cpp_strerror(-ret) << std::endl;
4847 return -ret;
4848 }
4849 } else {
4850 int ret = RGWBucketAdminOp::get_policy(store, bucket_op, f);
4851 if (ret < 0) {
4852 cerr << "ERROR: failed to get policy: " << cpp_strerror(-ret) << std::endl;
4853 return -ret;
4854 }
4855 }
4856 }
4857
4858 if (opt_cmd == OPT_BUCKETS_LIMIT_CHECK) {
4859 void *handle;
4860 std::list<std::string> user_ids;
4861 metadata_key = "user";
4862 int max = 1000;
4863
4864 bool truncated;
4865
4866 if (! user_id.empty()) {
4867 user_ids.push_back(user_id.id);
4868 ret =
4869 RGWBucketAdminOp::limit_check(store, bucket_op, user_ids, f,
4870 warnings_only);
4871 } else {
4872 /* list users in groups of max-keys, then perform user-bucket
4873 * limit-check on each group */
4874 ret = store->meta_mgr->list_keys_init(metadata_key, &handle);
4875 if (ret < 0) {
4876 cerr << "ERROR: buckets limit check can't get user metadata_key: "
4877 << cpp_strerror(-ret) << std::endl;
4878 return -ret;
4879 }
4880
4881 do {
4882 ret = store->meta_mgr->list_keys_next(handle, max, user_ids,
4883 &truncated);
4884 if (ret < 0 && ret != -ENOENT) {
4885 cerr << "ERROR: buckets limit check lists_keys_next(): "
4886 << cpp_strerror(-ret) << std::endl;
4887 break;
4888 } else {
4889 /* ok, do the limit checks for this group */
4890 ret =
4891 RGWBucketAdminOp::limit_check(store, bucket_op, user_ids, f,
4892 warnings_only);
4893 if (ret < 0)
4894 break;
4895 }
4896 user_ids.clear();
4897 } while (truncated);
4898 store->meta_mgr->list_keys_complete(handle);
4899 }
4900 return -ret;
4901 } /* OPT_BUCKETS_LIMIT_CHECK */
4902
4903 if (opt_cmd == OPT_BUCKETS_LIST) {
4904 if (bucket_name.empty()) {
4905 RGWBucketAdminOp::info(store, bucket_op, f);
4906 } else {
4907 RGWBucketInfo bucket_info;
4908 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
4909 if (ret < 0) {
4910 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
4911 return -ret;
4912 }
4913 formatter->open_array_section("entries");
4914 bool truncated;
4915 int count = 0;
4916 if (max_entries < 0)
4917 max_entries = 1000;
4918
4919 string prefix;
4920 string delim;
4921 vector<rgw_bucket_dir_entry> result;
4922 map<string, bool> common_prefixes;
4923 string ns;
4924
4925 RGWRados::Bucket target(store, bucket_info);
4926 RGWRados::Bucket::List list_op(&target);
4927
4928 list_op.params.prefix = prefix;
4929 list_op.params.delim = delim;
4930 list_op.params.marker = rgw_obj_key(marker);
4931 list_op.params.ns = ns;
4932 list_op.params.enforce_ns = false;
4933 list_op.params.list_versions = true;
4934
4935 do {
4936 ret = list_op.list_objects(max_entries - count, &result, &common_prefixes, &truncated);
4937 if (ret < 0) {
4938 cerr << "ERROR: store->list_objects(): " << cpp_strerror(-ret) << std::endl;
4939 return -ret;
4940 }
4941
4942 count += result.size();
4943
4944 for (vector<rgw_bucket_dir_entry>::iterator iter = result.begin(); iter != result.end(); ++iter) {
4945 rgw_bucket_dir_entry& entry = *iter;
4946 encode_json("entry", entry, formatter);
4947 }
4948 formatter->flush(cout);
4949 } while (truncated && count < max_entries);
4950
4951 formatter->close_section();
4952 formatter->flush(cout);
4953 } /* have bucket_name */
4954 } /* OPT_BUCKETS_LIST */
4955
4956 if (opt_cmd == OPT_BUCKET_STATS) {
4957 bucket_op.set_fetch_stats(true);
4958
4959 RGWBucketAdminOp::info(store, bucket_op, f);
4960 }
4961
4962 if (opt_cmd == OPT_BUCKET_LINK) {
4963 bucket_op.set_bucket_id(bucket_id);
4964 string err;
4965 int r = RGWBucketAdminOp::link(store, bucket_op, &err);
4966 if (r < 0) {
4967 cerr << "failure: " << cpp_strerror(-r) << ": " << err << std::endl;
4968 return -r;
4969 }
4970 }
4971
4972 if (opt_cmd == OPT_BUCKET_UNLINK) {
4973 int r = RGWBucketAdminOp::unlink(store, bucket_op);
4974 if (r < 0) {
4975 cerr << "failure: " << cpp_strerror(-r) << std::endl;
4976 return -r;
4977 }
4978 }
4979
4980 if (opt_cmd == OPT_LOG_LIST) {
4981 // filter by date?
4982 if (date.size() && date.size() != 10) {
4983 cerr << "bad date format for '" << date << "', expect YYYY-MM-DD" << std::endl;
4984 return EINVAL;
4985 }
4986
4987 formatter->reset();
4988 formatter->open_array_section("logs");
4989 RGWAccessHandle h;
4990 int r = store->log_list_init(date, &h);
4991 if (r == -ENOENT) {
4992 // no logs.
4993 } else {
4994 if (r < 0) {
4995 cerr << "log list: error " << r << std::endl;
4996 return -r;
4997 }
4998 while (true) {
4999 string name;
5000 int r = store->log_list_next(h, &name);
5001 if (r == -ENOENT)
5002 break;
5003 if (r < 0) {
5004 cerr << "log list: error " << r << std::endl;
5005 return -r;
5006 }
5007 formatter->dump_string("object", name);
5008 }
5009 }
5010 formatter->close_section();
5011 formatter->flush(cout);
5012 cout << std::endl;
5013 }
5014
5015 if (opt_cmd == OPT_LOG_SHOW || opt_cmd == OPT_LOG_RM) {
5016 if (object.empty() && (date.empty() || bucket_name.empty() || bucket_id.empty())) {
5017 cerr << "specify an object or a date, bucket and bucket-id" << std::endl;
5018 return usage();
5019 }
5020
5021 string oid;
5022 if (!object.empty()) {
5023 oid = object;
5024 } else {
5025 oid = date;
5026 oid += "-";
5027 oid += bucket_id;
5028 oid += "-";
5029 oid += bucket_name;
5030 }
5031
5032 if (opt_cmd == OPT_LOG_SHOW) {
5033 RGWAccessHandle h;
5034
5035 int r = store->log_show_init(oid, &h);
5036 if (r < 0) {
5037 cerr << "error opening log " << oid << ": " << cpp_strerror(-r) << std::endl;
5038 return -r;
5039 }
5040
5041 formatter->reset();
5042 formatter->open_object_section("log");
5043
5044 struct rgw_log_entry entry;
5045
5046 // peek at first entry to get bucket metadata
5047 r = store->log_show_next(h, &entry);
5048 if (r < 0) {
5049 cerr << "error reading log " << oid << ": " << cpp_strerror(-r) << std::endl;
5050 return -r;
5051 }
5052 formatter->dump_string("bucket_id", entry.bucket_id);
5053 formatter->dump_string("bucket_owner", entry.bucket_owner.to_str());
5054 formatter->dump_string("bucket", entry.bucket);
5055
5056 uint64_t agg_time = 0;
5057 uint64_t agg_bytes_sent = 0;
5058 uint64_t agg_bytes_received = 0;
5059 uint64_t total_entries = 0;
5060
5061 if (show_log_entries)
5062 formatter->open_array_section("log_entries");
5063
5064 do {
5065 uint64_t total_time = entry.total_time.sec() * 1000000LL + entry.total_time.usec();
5066
5067 agg_time += total_time;
5068 agg_bytes_sent += entry.bytes_sent;
5069 agg_bytes_received += entry.bytes_received;
5070 total_entries++;
5071
5072 if (skip_zero_entries && entry.bytes_sent == 0 &&
5073 entry.bytes_received == 0)
5074 goto next;
5075
5076 if (show_log_entries) {
5077
5078 rgw_format_ops_log_entry(entry, formatter);
5079 formatter->flush(cout);
5080 }
5081 next:
5082 r = store->log_show_next(h, &entry);
5083 } while (r > 0);
5084
5085 if (r < 0) {
5086 cerr << "error reading log " << oid << ": " << cpp_strerror(-r) << std::endl;
5087 return -r;
5088 }
5089 if (show_log_entries)
5090 formatter->close_section();
5091
5092 if (show_log_sum) {
5093 formatter->open_object_section("log_sum");
5094 formatter->dump_int("bytes_sent", agg_bytes_sent);
5095 formatter->dump_int("bytes_received", agg_bytes_received);
5096 formatter->dump_int("total_time", agg_time);
5097 formatter->dump_int("total_entries", total_entries);
5098 formatter->close_section();
5099 }
5100 formatter->close_section();
5101 formatter->flush(cout);
5102 cout << std::endl;
5103 }
5104 if (opt_cmd == OPT_LOG_RM) {
5105 int r = store->log_remove(oid);
5106 if (r < 0) {
5107 cerr << "error removing log " << oid << ": " << cpp_strerror(-r) << std::endl;
5108 return -r;
5109 }
5110 }
5111 }
5112
5113 if (opt_cmd == OPT_POOL_ADD) {
5114 if (pool_name.empty()) {
5115 cerr << "need to specify pool to add!" << std::endl;
5116 return usage();
5117 }
5118
5119 int ret = store->add_bucket_placement(pool);
5120 if (ret < 0)
5121 cerr << "failed to add bucket placement: " << cpp_strerror(-ret) << std::endl;
5122 }
5123
5124 if (opt_cmd == OPT_POOL_RM) {
5125 if (pool_name.empty()) {
5126 cerr << "need to specify pool to remove!" << std::endl;
5127 return usage();
5128 }
5129
5130 int ret = store->remove_bucket_placement(pool);
5131 if (ret < 0)
5132 cerr << "failed to remove bucket placement: " << cpp_strerror(-ret) << std::endl;
5133 }
5134
5135 if (opt_cmd == OPT_POOLS_LIST) {
5136 set<rgw_pool> pools;
5137 int ret = store->list_placement_set(pools);
5138 if (ret < 0) {
5139 cerr << "could not list placement set: " << cpp_strerror(-ret) << std::endl;
5140 return -ret;
5141 }
5142 formatter->reset();
5143 formatter->open_array_section("pools");
5144 for (auto siter = pools.begin(); siter != pools.end(); ++siter) {
5145 formatter->open_object_section("pool");
5146 formatter->dump_string("name", siter->to_str());
5147 formatter->close_section();
5148 }
5149 formatter->close_section();
5150 formatter->flush(cout);
5151 cout << std::endl;
5152 }
5153
5154 if (opt_cmd == OPT_USAGE_SHOW) {
5155 uint64_t start_epoch = 0;
5156 uint64_t end_epoch = (uint64_t)-1;
5157
5158 int ret;
5159
5160 if (!start_date.empty()) {
5161 ret = utime_t::parse_date(start_date, &start_epoch, NULL);
5162 if (ret < 0) {
5163 cerr << "ERROR: failed to parse start date" << std::endl;
5164 return 1;
5165 }
5166 }
5167 if (!end_date.empty()) {
5168 ret = utime_t::parse_date(end_date, &end_epoch, NULL);
5169 if (ret < 0) {
5170 cerr << "ERROR: failed to parse end date" << std::endl;
5171 return 1;
5172 }
5173 }
5174
5175
5176 ret = RGWUsage::show(store, user_id, start_epoch, end_epoch,
5177 show_log_entries, show_log_sum, &categories,
5178 f);
5179 if (ret < 0) {
5180 cerr << "ERROR: failed to show usage" << std::endl;
5181 return 1;
5182 }
5183 }
5184
5185 if (opt_cmd == OPT_USAGE_TRIM) {
5186 if (user_id.empty() && !yes_i_really_mean_it) {
5187 cerr << "usage trim without user specified will remove *all* users data" << std::endl;
5188 cerr << "do you really mean it? (requires --yes-i-really-mean-it)" << std::endl;
5189 return 1;
5190 }
5191 int ret;
5192 uint64_t start_epoch = 0;
5193 uint64_t end_epoch = (uint64_t)-1;
5194
5195
5196 if (!start_date.empty()) {
5197 ret = utime_t::parse_date(start_date, &start_epoch, NULL);
5198 if (ret < 0) {
5199 cerr << "ERROR: failed to parse start date" << std::endl;
5200 return 1;
5201 }
5202 }
5203
5204 if (!end_date.empty()) {
5205 ret = utime_t::parse_date(end_date, &end_epoch, NULL);
5206 if (ret < 0) {
5207 cerr << "ERROR: failed to parse end date" << std::endl;
5208 return 1;
5209 }
5210 }
5211
5212 ret = RGWUsage::trim(store, user_id, start_epoch, end_epoch);
5213 if (ret < 0) {
5214 cerr << "ERROR: read_usage() returned ret=" << ret << std::endl;
5215 return 1;
5216 }
5217 }
5218
5219 if (opt_cmd == OPT_OLH_GET || opt_cmd == OPT_OLH_READLOG) {
5220 if (bucket_name.empty()) {
5221 cerr << "ERROR: bucket not specified" << std::endl;
5222 return EINVAL;
5223 }
5224 if (object.empty()) {
5225 cerr << "ERROR: object not specified" << std::endl;
5226 return EINVAL;
5227 }
5228 RGWBucketInfo bucket_info;
5229 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
5230 if (ret < 0) {
5231 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
5232 return -ret;
5233 }
5234 }
5235
5236 if (opt_cmd == OPT_OLH_GET) {
5237 RGWBucketInfo bucket_info;
5238 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
5239 if (ret < 0) {
5240 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
5241 return -ret;
5242 }
5243 RGWOLHInfo olh;
5244 rgw_obj obj(bucket, object);
5245 ret = store->get_olh(bucket_info, obj, &olh);
5246 if (ret < 0) {
5247 cerr << "ERROR: failed reading olh: " << cpp_strerror(-ret) << std::endl;
5248 return -ret;
5249 }
5250 encode_json("olh", olh, formatter);
5251 formatter->flush(cout);
5252 }
5253
5254 if (opt_cmd == OPT_OLH_READLOG) {
5255 RGWBucketInfo bucket_info;
5256 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
5257 if (ret < 0) {
5258 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
5259 return -ret;
5260 }
5261 map<uint64_t, vector<rgw_bucket_olh_log_entry> > log;
5262 bool is_truncated;
5263
5264 RGWObjectCtx rctx(store);
5265 rgw_obj obj(bucket, object);
5266
5267 RGWObjState *state;
5268
5269 ret = store->get_obj_state(&rctx, bucket_info, obj, &state, false); /* don't follow olh */
5270 if (ret < 0) {
5271 return -ret;
5272 }
5273
5274 ret = store->bucket_index_read_olh_log(bucket_info, *state, obj, 0, &log, &is_truncated);
5275 if (ret < 0) {
5276 cerr << "ERROR: failed reading olh: " << cpp_strerror(-ret) << std::endl;
5277 return -ret;
5278 }
5279 formatter->open_object_section("result");
5280 encode_json("is_truncated", is_truncated, formatter);
5281 encode_json("log", log, formatter);
5282 formatter->close_section();
5283 formatter->flush(cout);
5284 }
5285
5286 if (opt_cmd == OPT_BI_GET) {
5287 RGWBucketInfo bucket_info;
5288 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
5289 if (ret < 0) {
5290 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
5291 return -ret;
5292 }
5293 rgw_obj obj(bucket, object);
5294 if (!object_version.empty()) {
5295 obj.key.set_instance(object_version);
5296 }
5297
5298 rgw_cls_bi_entry entry;
5299
5300 ret = store->bi_get(bucket, obj, bi_index_type, &entry);
5301 if (ret < 0) {
5302 cerr << "ERROR: bi_get(): " << cpp_strerror(-ret) << std::endl;
5303 return -ret;
5304 }
5305
5306 encode_json("entry", entry, formatter);
5307 formatter->flush(cout);
5308 }
5309
5310 if (opt_cmd == OPT_BI_PUT) {
5311 RGWBucketInfo bucket_info;
5312 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
5313 if (ret < 0) {
5314 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
5315 return -ret;
5316 }
5317
5318 rgw_cls_bi_entry entry;
5319 cls_rgw_obj_key key;
5320 ret = read_decode_json(infile, entry, &key);
5321 if (ret < 0) {
5322 return 1;
5323 }
5324
5325 rgw_obj obj(bucket, key);
5326
5327 ret = store->bi_put(bucket, obj, entry);
5328 if (ret < 0) {
5329 cerr << "ERROR: bi_put(): " << cpp_strerror(-ret) << std::endl;
5330 return -ret;
5331 }
5332 }
5333
5334 if (opt_cmd == OPT_BI_LIST) {
5335 if (bucket_name.empty()) {
5336 cerr << "ERROR: bucket name not specified" << std::endl;
5337 return EINVAL;
5338 }
5339 RGWBucketInfo bucket_info;
5340 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
5341 if (ret < 0) {
5342 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
5343 return -ret;
5344 }
5345
5346 list<rgw_cls_bi_entry> entries;
5347 bool is_truncated;
5348 if (max_entries < 0) {
5349 max_entries = 1000;
5350 }
5351
5352 int max_shards = (bucket_info.num_shards > 0 ? bucket_info.num_shards : 1);
5353
5354 formatter->open_array_section("entries");
5355
5356 for (int i = 0; i < max_shards; i++) {
5357 RGWRados::BucketShard bs(store);
5358 int shard_id = (bucket_info.num_shards > 0 ? i : -1);
5359 int ret = bs.init(bucket, shard_id);
5360 marker.clear();
5361
5362 if (ret < 0) {
5363 cerr << "ERROR: bs.init(bucket=" << bucket << ", shard=" << shard_id << "): " << cpp_strerror(-ret) << std::endl;
5364 return -ret;
5365 }
5366
5367 do {
5368 entries.clear();
5369 ret = store->bi_list(bs, object, marker, max_entries, &entries, &is_truncated);
5370 if (ret < 0) {
5371 cerr << "ERROR: bi_list(): " << cpp_strerror(-ret) << std::endl;
5372 return -ret;
5373 }
5374
5375 list<rgw_cls_bi_entry>::iterator iter;
5376 for (iter = entries.begin(); iter != entries.end(); ++iter) {
5377 rgw_cls_bi_entry& entry = *iter;
5378 encode_json("entry", entry, formatter);
5379 marker = entry.idx;
5380 }
5381 formatter->flush(cout);
5382 } while (is_truncated);
5383 formatter->flush(cout);
5384 }
5385 formatter->close_section();
5386 formatter->flush(cout);
5387 }
5388
5389 if (opt_cmd == OPT_BI_PURGE) {
5390 if (bucket_name.empty()) {
5391 cerr << "ERROR: bucket name not specified" << std::endl;
5392 return EINVAL;
5393 }
5394 RGWBucketInfo bucket_info;
5395 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
5396 if (ret < 0) {
5397 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
5398 return -ret;
5399 }
5400
5401 RGWBucketInfo cur_bucket_info;
5402 rgw_bucket cur_bucket;
5403 ret = init_bucket(tenant, bucket_name, string(), cur_bucket_info, cur_bucket);
5404 if (ret < 0) {
5405 cerr << "ERROR: could not init current bucket info for bucket_name=" << bucket_name << ": " << cpp_strerror(-ret) << std::endl;
5406 return -ret;
5407 }
5408
5409 if (cur_bucket_info.bucket.bucket_id == bucket_info.bucket.bucket_id && !yes_i_really_mean_it) {
5410 cerr << "specified bucket instance points to a current bucket instance" << std::endl;
5411 cerr << "do you really mean it? (requires --yes-i-really-mean-it)" << std::endl;
5412 return EINVAL;
5413 }
5414
5415 int max_shards = (bucket_info.num_shards > 0 ? bucket_info.num_shards : 1);
5416
5417 for (int i = 0; i < max_shards; i++) {
5418 RGWRados::BucketShard bs(store);
5419 int shard_id = (bucket_info.num_shards > 0 ? i : -1);
5420 int ret = bs.init(bucket, shard_id);
5421 if (ret < 0) {
5422 cerr << "ERROR: bs.init(bucket=" << bucket << ", shard=" << shard_id << "): " << cpp_strerror(-ret) << std::endl;
5423 return -ret;
5424 }
5425
5426 ret = store->bi_remove(bs);
5427 if (ret < 0) {
5428 cerr << "ERROR: failed to remove bucket index object: " << cpp_strerror(-ret) << std::endl;
5429 return -ret;
5430 }
5431 }
5432 }
5433
5434 if (opt_cmd == OPT_OBJECT_RM) {
5435 RGWBucketInfo bucket_info;
5436 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
5437 if (ret < 0) {
5438 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
5439 return -ret;
5440 }
5441 rgw_obj_key key(object, object_version);
5442 ret = rgw_remove_object(store, bucket_info, bucket, key);
5443
5444 if (ret < 0) {
5445 cerr << "ERROR: object remove returned: " << cpp_strerror(-ret) << std::endl;
5446 return -ret;
5447 }
5448 }
5449
5450 if (opt_cmd == OPT_OBJECT_REWRITE) {
5451 if (bucket_name.empty()) {
5452 cerr << "ERROR: bucket not specified" << std::endl;
5453 return EINVAL;
5454 }
5455 if (object.empty()) {
5456 cerr << "ERROR: object not specified" << std::endl;
5457 return EINVAL;
5458 }
5459
5460 RGWBucketInfo bucket_info;
5461 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
5462 if (ret < 0) {
5463 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
5464 return -ret;
5465 }
5466
5467 rgw_obj obj(bucket, object);
5468 obj.key.set_instance(object_version);
5469 bool need_rewrite = true;
5470 if (min_rewrite_stripe_size > 0) {
5471 ret = check_min_obj_stripe_size(store, bucket_info, obj, min_rewrite_stripe_size, &need_rewrite);
5472 if (ret < 0) {
5473 ldout(store->ctx(), 0) << "WARNING: check_min_obj_stripe_size failed, r=" << ret << dendl;
5474 }
5475 }
5476 if (need_rewrite) {
5477 ret = store->rewrite_obj(bucket_info, obj);
5478 if (ret < 0) {
5479 cerr << "ERROR: object rewrite returned: " << cpp_strerror(-ret) << std::endl;
5480 return -ret;
5481 }
5482 } else {
5483 ldout(store->ctx(), 20) << "skipped object" << dendl;
5484 }
5485 }
5486
5487 if (opt_cmd == OPT_OBJECTS_EXPIRE) {
5488 int ret = store->process_expire_objects();
5489 if (ret < 0) {
5490 cerr << "ERROR: process_expire_objects() processing returned error: " << cpp_strerror(-ret) << std::endl;
5491 return 1;
5492 }
5493 }
5494
5495 if (opt_cmd == OPT_BUCKET_REWRITE) {
5496 if (bucket_name.empty()) {
5497 cerr << "ERROR: bucket not specified" << std::endl;
5498 return EINVAL;
5499 }
5500
5501 RGWBucketInfo bucket_info;
5502 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
5503 if (ret < 0) {
5504 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
5505 return -ret;
5506 }
5507
5508 uint64_t start_epoch = 0;
5509 uint64_t end_epoch = 0;
5510
5511 if (!end_date.empty()) {
5512 int ret = utime_t::parse_date(end_date, &end_epoch, NULL);
5513 if (ret < 0) {
5514 cerr << "ERROR: failed to parse end date" << std::endl;
5515 return EINVAL;
5516 }
5517 }
5518 if (!start_date.empty()) {
5519 int ret = utime_t::parse_date(start_date, &start_epoch, NULL);
5520 if (ret < 0) {
5521 cerr << "ERROR: failed to parse start date" << std::endl;
5522 return EINVAL;
5523 }
5524 }
5525
5526 bool is_truncated = true;
5527
5528 rgw_obj_index_key marker;
5529 string prefix;
5530
5531 formatter->open_object_section("result");
5532 formatter->dump_string("bucket", bucket_name);
5533 formatter->open_array_section("objects");
5534 while (is_truncated) {
5535 map<string, rgw_bucket_dir_entry> result;
5536 int r = store->cls_bucket_list(bucket_info, RGW_NO_SHARD, marker, prefix, 1000, true,
5537 result, &is_truncated, &marker,
5538 bucket_object_check_filter);
5539
5540 if (r < 0 && r != -ENOENT) {
5541 cerr << "ERROR: failed operation r=" << r << std::endl;
5542 }
5543
5544 if (r == -ENOENT)
5545 break;
5546
5547 map<string, rgw_bucket_dir_entry>::iterator iter;
5548 for (iter = result.begin(); iter != result.end(); ++iter) {
5549 rgw_obj_key key = iter->second.key;
5550 rgw_bucket_dir_entry& entry = iter->second;
5551
5552 formatter->open_object_section("object");
5553 formatter->dump_string("name", key.name);
5554 formatter->dump_string("instance", key.instance);
5555 formatter->dump_int("size", entry.meta.size);
5556 utime_t ut(entry.meta.mtime);
5557 ut.gmtime(formatter->dump_stream("mtime"));
5558
5559 if ((entry.meta.size < min_rewrite_size) ||
5560 (entry.meta.size > max_rewrite_size) ||
5561 (start_epoch > 0 && start_epoch > (uint64_t)ut.sec()) ||
5562 (end_epoch > 0 && end_epoch < (uint64_t)ut.sec())) {
5563 formatter->dump_string("status", "Skipped");
5564 } else {
5565 rgw_obj obj(bucket, key);
5566
5567 bool need_rewrite = true;
5568 if (min_rewrite_stripe_size > 0) {
5569 r = check_min_obj_stripe_size(store, bucket_info, obj, min_rewrite_stripe_size, &need_rewrite);
5570 if (r < 0) {
5571 ldout(store->ctx(), 0) << "WARNING: check_min_obj_stripe_size failed, r=" << r << dendl;
5572 }
5573 }
5574 if (!need_rewrite) {
5575 formatter->dump_string("status", "Skipped");
5576 } else {
5577 r = store->rewrite_obj(bucket_info, obj);
5578 if (r == 0) {
5579 formatter->dump_string("status", "Success");
5580 } else {
5581 formatter->dump_string("status", cpp_strerror(-r));
5582 }
5583 }
5584 }
5585 formatter->dump_int("flags", entry.flags);
5586
5587 formatter->close_section();
5588 formatter->flush(cout);
5589 }
5590 }
5591 formatter->close_section();
5592 formatter->close_section();
5593 formatter->flush(cout);
5594 }
5595
5596 if (opt_cmd == OPT_BUCKET_RESHARD) {
5597 if (bucket_name.empty()) {
5598 cerr << "ERROR: bucket not specified" << std::endl;
5599 return EINVAL;
5600 }
5601
5602 if (!num_shards_specified) {
5603 cerr << "ERROR: --num-shards not specified" << std::endl;
5604 return EINVAL;
5605 }
5606
5607 if (num_shards > (int)store->get_max_bucket_shards()) {
5608 cerr << "ERROR: num_shards too high, max value: " << store->get_max_bucket_shards() << std::endl;
5609 return EINVAL;
5610 }
5611
5612 RGWBucketInfo bucket_info;
5613 map<string, bufferlist> attrs;
5614 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket, &attrs);
5615 if (ret < 0) {
5616 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
5617 return -ret;
5618 }
5619
5620 int num_source_shards = (bucket_info.num_shards > 0 ? bucket_info.num_shards : 1);
5621
5622 if (num_shards <= num_source_shards && !yes_i_really_mean_it) {
5623 cerr << "num shards is less or equal to current shards count" << std::endl
5624 << "do you really mean it? (requires --yes-i-really-mean-it)" << std::endl;
5625 return EINVAL;
5626 }
5627
5628 RGWBucketInfo new_bucket_info(bucket_info);
5629 store->create_bucket_id(&new_bucket_info.bucket.bucket_id);
5630 new_bucket_info.bucket.oid.clear();
5631
5632 new_bucket_info.num_shards = num_shards;
5633 new_bucket_info.objv_tracker.clear();
5634
5635 cout << "*** NOTICE: operation will not remove old bucket index objects ***" << std::endl;
5636 cout << "*** these will need to be removed manually ***" << std::endl;
5637 cout << "old bucket instance id: " << bucket_info.bucket.bucket_id << std::endl;
5638 cout << "new bucket instance id: " << new_bucket_info.bucket.bucket_id << std::endl;
5639
5640 ret = store->init_bucket_index(new_bucket_info, new_bucket_info.num_shards);
5641 if (ret < 0) {
5642 cerr << "ERROR: failed to init new bucket indexes: " << cpp_strerror(-ret) << std::endl;
5643 return -ret;
5644 }
5645
5646 ret = store->put_bucket_instance_info(new_bucket_info, true, real_time(), &attrs);
5647 if (ret < 0) {
5648 cerr << "ERROR: failed to store new bucket instance info: " << cpp_strerror(-ret) << std::endl;
5649 return -ret;
5650 }
5651 list<rgw_cls_bi_entry> entries;
5652
5653 if (max_entries < 0) {
5654 max_entries = 1000;
5655 }
5656
5657 int num_target_shards = (new_bucket_info.num_shards > 0 ? new_bucket_info.num_shards : 1);
5658
5659 BucketReshardManager target_shards_mgr(store, new_bucket_info, num_target_shards);
5660
5661 if (verbose) {
5662 formatter->open_array_section("entries");
5663 }
5664
5665 uint64_t total_entries = 0;
5666
5667 if (!verbose) {
5668 cout << "total entries:";
5669 }
5670
5671 for (int i = 0; i < num_source_shards; ++i) {
5672 bool is_truncated = true;
5673 marker.clear();
5674 while (is_truncated) {
5675 entries.clear();
5676 ret = store->bi_list(bucket, i, string(), marker, max_entries, &entries, &is_truncated);
5677 if (ret < 0) {
5678 cerr << "ERROR: bi_list(): " << cpp_strerror(-ret) << std::endl;
5679 return -ret;
5680 }
5681
5682 list<rgw_cls_bi_entry>::iterator iter;
5683 for (iter = entries.begin(); iter != entries.end(); ++iter) {
5684 rgw_cls_bi_entry& entry = *iter;
5685 if (verbose) {
5686 formatter->open_object_section("entry");
5687
5688 encode_json("shard_id", i, formatter);
5689 encode_json("num_entry", total_entries, formatter);
5690 encode_json("entry", entry, formatter);
5691 }
5692 total_entries++;
5693
5694 marker = entry.idx;
5695
5696 int target_shard_id;
5697 cls_rgw_obj_key cls_key;
5698 uint8_t category;
5699 rgw_bucket_category_stats stats;
5700 bool account = entry.get_info(&cls_key, &category, &stats);
5701 rgw_obj_key key(cls_key);
5702 rgw_obj obj(new_bucket_info.bucket, key);
5703 int ret = store->get_target_shard_id(new_bucket_info, obj.get_hash_object(), &target_shard_id);
5704 if (ret < 0) {
5705 cerr << "ERROR: get_target_shard_id() returned ret=" << ret << std::endl;
5706 return ret;
5707 }
5708
5709 int shard_index = (target_shard_id > 0 ? target_shard_id : 0);
5710
5711 ret = target_shards_mgr.add_entry(shard_index, entry, account, category, stats);
5712 if (ret < 0) {
5713 return ret;
5714 }
5715 if (verbose) {
5716 formatter->close_section();
5717 formatter->flush(cout);
5718 formatter->flush(cout);
5719 } else if (!(total_entries % 1000)) {
5720 cout << " " << total_entries;
5721 }
5722 }
5723 }
5724 }
5725 if (verbose) {
5726 formatter->close_section();
5727 formatter->flush(cout);
5728 } else {
5729 cout << " " << total_entries << std::endl;
5730 }
5731
5732 ret = target_shards_mgr.finish();
5733 if (ret < 0) {
5734 cerr << "ERROR: failed to reshard" << std::endl;
5735 return EIO;
5736 }
5737
5738 bucket_op.set_bucket_id(new_bucket_info.bucket.bucket_id);
5739 bucket_op.set_user_id(new_bucket_info.owner);
5740 string err;
5741 int r = RGWBucketAdminOp::link(store, bucket_op, &err);
5742 if (r < 0) {
5743 cerr << "failed to link new bucket instance (bucket_id=" << new_bucket_info.bucket.bucket_id << ": " << err << "; " << cpp_strerror(-r) << std::endl;
5744 return -r;
5745 }
5746 }
5747
5748 if (opt_cmd == OPT_OBJECT_UNLINK) {
5749 RGWBucketInfo bucket_info;
5750 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
5751 if (ret < 0) {
5752 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
5753 return -ret;
5754 }
5755 list<rgw_obj_index_key> oid_list;
5756 rgw_obj_key key(object, object_version);
5757 rgw_obj_index_key index_key;
5758 key.get_index_key(&index_key);
5759 oid_list.push_back(index_key);
5760 ret = store->remove_objs_from_index(bucket_info, oid_list);
5761 if (ret < 0) {
5762 cerr << "ERROR: remove_obj_from_index() returned error: " << cpp_strerror(-ret) << std::endl;
5763 return 1;
5764 }
5765 }
5766
5767 if (opt_cmd == OPT_OBJECT_STAT) {
5768 RGWBucketInfo bucket_info;
5769 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
5770 if (ret < 0) {
5771 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
5772 return -ret;
5773 }
5774 rgw_obj obj(bucket, object);
5775 obj.key.set_instance(object_version);
5776
5777 uint64_t obj_size;
5778 map<string, bufferlist> attrs;
5779 RGWObjectCtx obj_ctx(store);
5780 RGWRados::Object op_target(store, bucket_info, obj_ctx, obj);
5781 RGWRados::Object::Read read_op(&op_target);
5782
5783 read_op.params.attrs = &attrs;
5784 read_op.params.obj_size = &obj_size;
5785
5786 ret = read_op.prepare();
5787 if (ret < 0) {
5788 cerr << "ERROR: failed to stat object, returned error: " << cpp_strerror(-ret) << std::endl;
5789 return 1;
5790 }
5791 formatter->open_object_section("object_metadata");
5792 formatter->dump_string("name", object);
5793 formatter->dump_unsigned("size", obj_size);
5794
5795 map<string, bufferlist>::iterator iter;
5796 map<string, bufferlist> other_attrs;
5797 for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
5798 bufferlist& bl = iter->second;
5799 bool handled = false;
5800 if (iter->first == RGW_ATTR_MANIFEST) {
5801 handled = decode_dump<RGWObjManifest>("manifest", bl, formatter);
5802 } else if (iter->first == RGW_ATTR_ACL) {
5803 handled = decode_dump<RGWAccessControlPolicy>("policy", bl, formatter);
5804 } else if (iter->first == RGW_ATTR_ID_TAG) {
5805 handled = dump_string("tag", bl, formatter);
5806 } else if (iter->first == RGW_ATTR_ETAG) {
5807 handled = dump_string("etag", bl, formatter);
5808 }
5809
5810 if (!handled)
5811 other_attrs[iter->first] = bl;
5812 }
5813
5814 formatter->open_object_section("attrs");
5815 for (iter = other_attrs.begin(); iter != other_attrs.end(); ++iter) {
5816 dump_string(iter->first.c_str(), iter->second, formatter);
5817 }
5818 formatter->close_section();
5819 formatter->close_section();
5820 formatter->flush(cout);
5821 }
5822
5823 if (opt_cmd == OPT_BUCKET_CHECK) {
5824 if (check_head_obj_locator) {
5825 if (bucket_name.empty()) {
5826 cerr << "ERROR: need to specify bucket name" << std::endl;
5827 return EINVAL;
5828 }
5829 do_check_object_locator(tenant, bucket_name, fix, remove_bad, formatter);
5830 } else {
5831 RGWBucketAdminOp::check_index(store, bucket_op, f);
5832 }
5833 }
5834
5835 if (opt_cmd == OPT_BUCKET_RM) {
5836 if (inconsistent_index == false) {
5837 RGWBucketAdminOp::remove_bucket(store, bucket_op, bypass_gc, true);
5838 } else {
5839 RGWBucketAdminOp::remove_bucket(store, bucket_op, bypass_gc, false);
5840 }
5841 }
5842
5843 if (opt_cmd == OPT_GC_LIST) {
5844 int index = 0;
5845 bool truncated;
5846 formatter->open_array_section("entries");
5847
5848 do {
5849 list<cls_rgw_gc_obj_info> result;
5850 int ret = store->list_gc_objs(&index, marker, 1000, !include_all, result, &truncated);
5851 if (ret < 0) {
5852 cerr << "ERROR: failed to list objs: " << cpp_strerror(-ret) << std::endl;
5853 return 1;
5854 }
5855
5856
5857 list<cls_rgw_gc_obj_info>::iterator iter;
5858 for (iter = result.begin(); iter != result.end(); ++iter) {
5859 cls_rgw_gc_obj_info& info = *iter;
5860 formatter->open_object_section("chain_info");
5861 formatter->dump_string("tag", info.tag);
5862 formatter->dump_stream("time") << info.time;
5863 formatter->open_array_section("objs");
5864 list<cls_rgw_obj>::iterator liter;
5865 cls_rgw_obj_chain& chain = info.chain;
5866 for (liter = chain.objs.begin(); liter != chain.objs.end(); ++liter) {
5867 cls_rgw_obj& obj = *liter;
5868 encode_json("obj", obj, formatter);
5869 }
5870 formatter->close_section(); // objs
5871 formatter->close_section(); // obj_chain
5872 formatter->flush(cout);
5873 }
5874 } while (truncated);
5875 formatter->close_section();
5876 formatter->flush(cout);
5877 }
5878
5879 if (opt_cmd == OPT_GC_PROCESS) {
5880 int ret = store->process_gc();
5881 if (ret < 0) {
5882 cerr << "ERROR: gc processing returned error: " << cpp_strerror(-ret) << std::endl;
5883 return 1;
5884 }
5885 }
5886
5887 if (opt_cmd == OPT_LC_LIST) {
5888 formatter->open_array_section("lifecycle_list");
5889 map<string, int> bucket_lc_map;
5890 string marker;
5891 #define MAX_LC_LIST_ENTRIES 100
5892 if (max_entries < 0) {
5893 max_entries = MAX_LC_LIST_ENTRIES;
5894 }
5895 do {
5896 int ret = store->list_lc_progress(marker, max_entries, &bucket_lc_map);
5897 if (ret < 0) {
5898 cerr << "ERROR: failed to list objs: " << cpp_strerror(-ret) << std::endl;
5899 return 1;
5900 }
5901 map<string, int>::iterator iter;
5902 for (iter = bucket_lc_map.begin(); iter != bucket_lc_map.end(); ++iter) {
5903 formatter->open_object_section("bucket_lc_info");
5904 formatter->dump_string("bucket", iter->first);
5905 string lc_status = LC_STATUS[iter->second];
5906 formatter->dump_string("status", lc_status);
5907 formatter->close_section(); // objs
5908 formatter->flush(cout);
5909 marker = iter->first;
5910 }
5911 } while (!bucket_lc_map.empty());
5912
5913 formatter->close_section(); //lifecycle list
5914 formatter->flush(cout);
5915 }
5916
5917
5918 if (opt_cmd == OPT_LC_PROCESS) {
5919 int ret = store->process_lc();
5920 if (ret < 0) {
5921 cerr << "ERROR: lc processing returned error: " << cpp_strerror(-ret) << std::endl;
5922 return 1;
5923 }
5924 }
5925
5926 if (opt_cmd == OPT_ORPHANS_FIND) {
5927 RGWOrphanSearch search(store, max_concurrent_ios, orphan_stale_secs);
5928
5929 if (job_id.empty()) {
5930 cerr << "ERROR: --job-id not specified" << std::endl;
5931 return EINVAL;
5932 }
5933 if (pool_name.empty()) {
5934 cerr << "ERROR: --pool not specified" << std::endl;
5935 return EINVAL;
5936 }
5937
5938 RGWOrphanSearchInfo info;
5939
5940 info.pool = pool;
5941 info.job_name = job_id;
5942 info.num_shards = num_shards;
5943
5944 int ret = search.init(job_id, &info);
5945 if (ret < 0) {
5946 cerr << "could not init search, ret=" << ret << std::endl;
5947 return -ret;
5948 }
5949 ret = search.run();
5950 if (ret < 0) {
5951 return -ret;
5952 }
5953 }
5954
5955 if (opt_cmd == OPT_ORPHANS_FINISH) {
5956 RGWOrphanSearch search(store, max_concurrent_ios, orphan_stale_secs);
5957
5958 if (job_id.empty()) {
5959 cerr << "ERROR: --job-id not specified" << std::endl;
5960 return EINVAL;
5961 }
5962 int ret = search.init(job_id, NULL);
5963 if (ret < 0) {
5964 if (ret == -ENOENT) {
5965 cerr << "job not found" << std::endl;
5966 }
5967 return -ret;
5968 }
5969 ret = search.finish();
5970 if (ret < 0) {
5971 return -ret;
5972 }
5973 }
5974
5975 if (opt_cmd == OPT_ORPHANS_LIST_JOBS){
5976 RGWOrphanStore orphan_store(store);
5977 int ret = orphan_store.init();
5978 if (ret < 0){
5979 cerr << "connection to cluster failed!" << std::endl;
5980 return -ret;
5981 }
5982
5983 map <string,RGWOrphanSearchState> m;
5984 ret = orphan_store.list_jobs(m);
5985 if (ret < 0) {
5986 cerr << "job list failed" << std::endl;
5987 return -ret;
5988 }
5989 formatter->open_array_section("entries");
5990 for (const auto &it: m){
5991 if (!extra_info){
5992 formatter->dump_string("job-id",it.first);
5993 } else {
5994 encode_json("orphan_search_state", it.second, formatter);
5995 }
5996 }
5997 formatter->close_section();
5998 formatter->flush(cout);
5999 }
6000
6001 if (opt_cmd == OPT_USER_CHECK) {
6002 check_bad_user_bucket_mapping(store, user_id, fix);
6003 }
6004
6005 if (opt_cmd == OPT_USER_STATS) {
6006 if (sync_stats) {
6007 if (!bucket_name.empty()) {
6008 int ret = rgw_bucket_sync_user_stats(store, tenant, bucket_name);
6009 if (ret < 0) {
6010 cerr << "ERROR: could not sync bucket stats: " << cpp_strerror(-ret) << std::endl;
6011 return -ret;
6012 }
6013 } else {
6014 int ret = rgw_user_sync_all_stats(store, user_id);
6015 if (ret < 0) {
6016 cerr << "ERROR: failed to sync user stats: " << cpp_strerror(-ret) << std::endl;
6017 return -ret;
6018 }
6019 }
6020 }
6021
6022 if (user_id.empty()) {
6023 cerr << "ERROR: uid not specified" << std::endl;
6024 return EINVAL;
6025 }
6026 cls_user_header header;
6027 string user_str = user_id.to_str();
6028 int ret = store->cls_user_get_header(user_str, &header);
6029 if (ret < 0) {
6030 if (ret == -ENOENT) { /* in case of ENOENT */
6031 cerr << "User has not been initialized or user does not exist" << std::endl;
6032 } else {
6033 cerr << "ERROR: can't read user: " << cpp_strerror(ret) << std::endl;
6034 }
6035 return -ret;
6036 }
6037
6038 encode_json("header", header, formatter);
6039 formatter->flush(cout);
6040 }
6041
6042 if (opt_cmd == OPT_METADATA_GET) {
6043 int ret = store->meta_mgr->get(metadata_key, formatter);
6044 if (ret < 0) {
6045 cerr << "ERROR: can't get key: " << cpp_strerror(-ret) << std::endl;
6046 return -ret;
6047 }
6048
6049 formatter->flush(cout);
6050 }
6051
6052 if (opt_cmd == OPT_METADATA_PUT) {
6053 bufferlist bl;
6054 int ret = read_input(infile, bl);
6055 if (ret < 0) {
6056 cerr << "ERROR: failed to read input: " << cpp_strerror(-ret) << std::endl;
6057 return -ret;
6058 }
6059 ret = store->meta_mgr->put(metadata_key, bl, RGWMetadataHandler::APPLY_ALWAYS);
6060 if (ret < 0) {
6061 cerr << "ERROR: can't put key: " << cpp_strerror(-ret) << std::endl;
6062 return -ret;
6063 }
6064 }
6065
6066 if (opt_cmd == OPT_METADATA_RM) {
6067 int ret = store->meta_mgr->remove(metadata_key);
6068 if (ret < 0) {
6069 cerr << "ERROR: can't remove key: " << cpp_strerror(-ret) << std::endl;
6070 return -ret;
6071 }
6072 }
6073
6074 if (opt_cmd == OPT_METADATA_LIST || opt_cmd == OPT_USER_LIST) {
6075 if (opt_cmd == OPT_USER_LIST) {
6076 metadata_key = "user";
6077 }
6078 void *handle;
6079 int max = 1000;
6080 int ret = store->meta_mgr->list_keys_init(metadata_key, &handle);
6081 if (ret < 0) {
6082 cerr << "ERROR: can't get key: " << cpp_strerror(-ret) << std::endl;
6083 return -ret;
6084 }
6085
6086 bool truncated;
6087
6088 formatter->open_array_section("keys");
6089
6090 do {
6091 list<string> keys;
6092 ret = store->meta_mgr->list_keys_next(handle, max, keys, &truncated);
6093 if (ret < 0 && ret != -ENOENT) {
6094 cerr << "ERROR: lists_keys_next(): " << cpp_strerror(-ret) << std::endl;
6095 return -ret;
6096 } if (ret != -ENOENT) {
6097 for (list<string>::iterator iter = keys.begin(); iter != keys.end(); ++iter) {
6098 formatter->dump_string("key", *iter);
6099 }
6100 formatter->flush(cout);
6101 }
6102 } while (truncated);
6103
6104 formatter->close_section();
6105 formatter->flush(cout);
6106
6107 store->meta_mgr->list_keys_complete(handle);
6108 }
6109
6110 if (opt_cmd == OPT_MDLOG_LIST) {
6111 utime_t start_time, end_time;
6112
6113 int ret = parse_date_str(start_date, start_time);
6114 if (ret < 0)
6115 return -ret;
6116
6117 ret = parse_date_str(end_date, end_time);
6118 if (ret < 0)
6119 return -ret;
6120
6121 int i = (specified_shard_id ? shard_id : 0);
6122
6123 if (period_id.empty()) {
6124 int ret = read_current_period_id(store, realm_id, realm_name, &period_id);
6125 if (ret < 0) {
6126 return -ret;
6127 }
6128 std::cerr << "No --period given, using current period="
6129 << period_id << std::endl;
6130 }
6131 RGWMetadataLog *meta_log = store->meta_mgr->get_log(period_id);
6132
6133 formatter->open_array_section("entries");
6134 for (; i < g_ceph_context->_conf->rgw_md_log_max_shards; i++) {
6135 void *handle;
6136 list<cls_log_entry> entries;
6137
6138
6139 meta_log->init_list_entries(i, start_time.to_real_time(), end_time.to_real_time(), marker, &handle);
6140 bool truncated;
6141 do {
6142 int ret = meta_log->list_entries(handle, 1000, entries, NULL, &truncated);
6143 if (ret < 0) {
6144 cerr << "ERROR: meta_log->list_entries(): " << cpp_strerror(-ret) << std::endl;
6145 return -ret;
6146 }
6147
6148 for (list<cls_log_entry>::iterator iter = entries.begin(); iter != entries.end(); ++iter) {
6149 cls_log_entry& entry = *iter;
6150 store->meta_mgr->dump_log_entry(entry, formatter);
6151 }
6152 formatter->flush(cout);
6153 } while (truncated);
6154
6155 meta_log->complete_list_entries(handle);
6156
6157 if (specified_shard_id)
6158 break;
6159 }
6160
6161
6162 formatter->close_section();
6163 formatter->flush(cout);
6164 }
6165
6166 if (opt_cmd == OPT_MDLOG_STATUS) {
6167 int i = (specified_shard_id ? shard_id : 0);
6168
6169 if (period_id.empty()) {
6170 int ret = read_current_period_id(store, realm_id, realm_name, &period_id);
6171 if (ret < 0) {
6172 return -ret;
6173 }
6174 std::cerr << "No --period given, using current period="
6175 << period_id << std::endl;
6176 }
6177 RGWMetadataLog *meta_log = store->meta_mgr->get_log(period_id);
6178
6179 formatter->open_array_section("entries");
6180
6181 for (; i < g_ceph_context->_conf->rgw_md_log_max_shards; i++) {
6182 RGWMetadataLogInfo info;
6183 meta_log->get_info(i, &info);
6184
6185 ::encode_json("info", info, formatter);
6186
6187 if (specified_shard_id)
6188 break;
6189 }
6190
6191
6192 formatter->close_section();
6193 formatter->flush(cout);
6194 }
6195
6196 if (opt_cmd == OPT_MDLOG_AUTOTRIM) {
6197 // need a full history for purging old mdlog periods
6198 store->meta_mgr->init_oldest_log_period();
6199
6200 RGWCoroutinesManager crs(store->ctx(), store->get_cr_registry());
6201 RGWHTTPManager http(store->ctx(), crs.get_completion_mgr());
6202 int ret = http.set_threaded();
6203 if (ret < 0) {
6204 cerr << "failed to initialize http client with " << cpp_strerror(ret) << std::endl;
6205 return -ret;
6206 }
6207
6208 auto num_shards = g_conf->rgw_md_log_max_shards;
6209 ret = crs.run(create_admin_meta_log_trim_cr(store, &http, num_shards));
6210 if (ret < 0) {
6211 cerr << "automated mdlog trim failed with " << cpp_strerror(ret) << std::endl;
6212 return -ret;
6213 }
6214 }
6215
6216 if (opt_cmd == OPT_MDLOG_TRIM) {
6217 utime_t start_time, end_time;
6218
6219 if (!specified_shard_id) {
6220 cerr << "ERROR: shard-id must be specified for trim operation" << std::endl;
6221 return EINVAL;
6222 }
6223
6224 int ret = parse_date_str(start_date, start_time);
6225 if (ret < 0)
6226 return -ret;
6227
6228 ret = parse_date_str(end_date, end_time);
6229 if (ret < 0)
6230 return -ret;
6231
6232 if (period_id.empty()) {
6233 std::cerr << "missing --period argument" << std::endl;
6234 return EINVAL;
6235 }
6236 RGWMetadataLog *meta_log = store->meta_mgr->get_log(period_id);
6237
6238 ret = meta_log->trim(shard_id, start_time.to_real_time(), end_time.to_real_time(), start_marker, end_marker);
6239 if (ret < 0) {
6240 cerr << "ERROR: meta_log->trim(): " << cpp_strerror(-ret) << std::endl;
6241 return -ret;
6242 }
6243 }
6244
6245 if (opt_cmd == OPT_SYNC_STATUS) {
6246 sync_status(formatter);
6247 }
6248
6249 if (opt_cmd == OPT_METADATA_SYNC_STATUS) {
6250 RGWMetaSyncStatusManager sync(store, store->get_async_rados());
6251
6252 int ret = sync.init();
6253 if (ret < 0) {
6254 cerr << "ERROR: sync.init() returned ret=" << ret << std::endl;
6255 return -ret;
6256 }
6257
6258 rgw_meta_sync_status sync_status;
6259 ret = sync.read_sync_status(&sync_status);
6260 if (ret < 0) {
6261 cerr << "ERROR: sync.read_sync_status() returned ret=" << ret << std::endl;
6262 return -ret;
6263 }
6264
6265 formatter->open_object_section("summary");
6266 encode_json("sync_status", sync_status, formatter);
6267
6268 uint64_t full_total = 0;
6269 uint64_t full_complete = 0;
6270
6271 for (auto marker_iter : sync_status.sync_markers) {
6272 full_total += marker_iter.second.total_entries;
6273 if (marker_iter.second.state == rgw_meta_sync_marker::SyncState::FullSync) {
6274 full_complete += marker_iter.second.pos;
6275 } else {
6276 full_complete += marker_iter.second.total_entries;
6277 }
6278 }
6279
6280 formatter->open_object_section("full_sync");
6281 encode_json("total", full_total, formatter);
6282 encode_json("complete", full_complete, formatter);
6283 formatter->close_section();
6284 formatter->close_section();
6285
6286 formatter->flush(cout);
6287
6288 }
6289
6290 if (opt_cmd == OPT_METADATA_SYNC_INIT) {
6291 RGWMetaSyncStatusManager sync(store, store->get_async_rados());
6292
6293 int ret = sync.init();
6294 if (ret < 0) {
6295 cerr << "ERROR: sync.init() returned ret=" << ret << std::endl;
6296 return -ret;
6297 }
6298 ret = sync.init_sync_status();
6299 if (ret < 0) {
6300 cerr << "ERROR: sync.init_sync_status() returned ret=" << ret << std::endl;
6301 return -ret;
6302 }
6303 }
6304
6305
6306 if (opt_cmd == OPT_METADATA_SYNC_RUN) {
6307 RGWMetaSyncStatusManager sync(store, store->get_async_rados());
6308
6309 int ret = sync.init();
6310 if (ret < 0) {
6311 cerr << "ERROR: sync.init() returned ret=" << ret << std::endl;
6312 return -ret;
6313 }
6314
6315 ret = sync.run();
6316 if (ret < 0) {
6317 cerr << "ERROR: sync.run() returned ret=" << ret << std::endl;
6318 return -ret;
6319 }
6320 }
6321
6322 if (opt_cmd == OPT_DATA_SYNC_STATUS) {
6323 if (source_zone.empty()) {
6324 cerr << "ERROR: source zone not specified" << std::endl;
6325 return EINVAL;
6326 }
6327 RGWDataSyncStatusManager sync(store, store->get_async_rados(), source_zone);
6328
6329 int ret = sync.init();
6330 if (ret < 0) {
6331 cerr << "ERROR: sync.init() returned ret=" << ret << std::endl;
6332 return -ret;
6333 }
6334
6335 rgw_data_sync_status sync_status;
6336 ret = sync.read_sync_status(&sync_status);
6337 if (ret < 0 && ret != -ENOENT) {
6338 cerr << "ERROR: sync.read_sync_status() returned ret=" << ret << std::endl;
6339 return -ret;
6340 }
6341
6342 formatter->open_object_section("summary");
6343 encode_json("sync_status", sync_status, formatter);
6344
6345 uint64_t full_total = 0;
6346 uint64_t full_complete = 0;
6347
6348 for (auto marker_iter : sync_status.sync_markers) {
6349 full_total += marker_iter.second.total_entries;
6350 if (marker_iter.second.state == rgw_meta_sync_marker::SyncState::FullSync) {
6351 full_complete += marker_iter.second.pos;
6352 } else {
6353 full_complete += marker_iter.second.total_entries;
6354 }
6355 }
6356
6357 formatter->open_object_section("full_sync");
6358 encode_json("total", full_total, formatter);
6359 encode_json("complete", full_complete, formatter);
6360 formatter->close_section();
6361 formatter->close_section();
6362
6363 formatter->flush(cout);
6364 }
6365
6366 if (opt_cmd == OPT_DATA_SYNC_INIT) {
6367 if (source_zone.empty()) {
6368 cerr << "ERROR: source zone not specified" << std::endl;
6369 return EINVAL;
6370 }
6371 RGWDataSyncStatusManager sync(store, store->get_async_rados(), source_zone);
6372
6373 int ret = sync.init();
6374 if (ret < 0) {
6375 cerr << "ERROR: sync.init() returned ret=" << ret << std::endl;
6376 return -ret;
6377 }
6378
6379 ret = sync.init_sync_status();
6380 if (ret < 0) {
6381 cerr << "ERROR: sync.init_sync_status() returned ret=" << ret << std::endl;
6382 return -ret;
6383 }
6384 }
6385
6386 if (opt_cmd == OPT_DATA_SYNC_RUN) {
6387 if (source_zone.empty()) {
6388 cerr << "ERROR: source zone not specified" << std::endl;
6389 return EINVAL;
6390 }
6391 RGWDataSyncStatusManager sync(store, store->get_async_rados(), source_zone);
6392
6393 int ret = sync.init();
6394 if (ret < 0) {
6395 cerr << "ERROR: sync.init() returned ret=" << ret << std::endl;
6396 return -ret;
6397 }
6398
6399 ret = sync.run();
6400 if (ret < 0) {
6401 cerr << "ERROR: sync.run() returned ret=" << ret << std::endl;
6402 return -ret;
6403 }
6404 }
6405
6406 if (opt_cmd == OPT_BUCKET_SYNC_INIT) {
6407 if (source_zone.empty()) {
6408 cerr << "ERROR: source zone not specified" << std::endl;
6409 return EINVAL;
6410 }
6411 if (bucket_name.empty()) {
6412 cerr << "ERROR: bucket not specified" << std::endl;
6413 return EINVAL;
6414 }
6415 rgw_bucket bucket;
6416 int ret = init_bucket_for_sync(tenant, bucket_name, bucket_id, bucket);
6417 if (ret < 0) {
6418 return -ret;
6419 }
6420 RGWBucketSyncStatusManager sync(store, source_zone, bucket);
6421
6422 ret = sync.init();
6423 if (ret < 0) {
6424 cerr << "ERROR: sync.init() returned ret=" << ret << std::endl;
6425 return -ret;
6426 }
6427 ret = sync.init_sync_status();
6428 if (ret < 0) {
6429 cerr << "ERROR: sync.init_sync_status() returned ret=" << ret << std::endl;
6430 return -ret;
6431 }
6432 }
6433
6434 if (opt_cmd == OPT_BUCKET_SYNC_STATUS) {
6435 if (source_zone.empty()) {
6436 cerr << "ERROR: source zone not specified" << std::endl;
6437 return EINVAL;
6438 }
6439 if (bucket_name.empty()) {
6440 cerr << "ERROR: bucket not specified" << std::endl;
6441 return EINVAL;
6442 }
6443 rgw_bucket bucket;
6444 int ret = init_bucket_for_sync(tenant, bucket_name, bucket_id, bucket);
6445 if (ret < 0) {
6446 return -ret;
6447 }
6448 RGWBucketSyncStatusManager sync(store, source_zone, bucket);
6449
6450 ret = sync.init();
6451 if (ret < 0) {
6452 cerr << "ERROR: sync.init() returned ret=" << ret << std::endl;
6453 return -ret;
6454 }
6455 ret = sync.read_sync_status();
6456 if (ret < 0) {
6457 cerr << "ERROR: sync.read_sync_status() returned ret=" << ret << std::endl;
6458 return -ret;
6459 }
6460
6461 map<int, rgw_bucket_shard_sync_info>& sync_status = sync.get_sync_status();
6462
6463 encode_json("sync_status", sync_status, formatter);
6464 formatter->flush(cout);
6465 }
6466
6467 if (opt_cmd == OPT_BUCKET_SYNC_RUN) {
6468 if (source_zone.empty()) {
6469 cerr << "ERROR: source zone not specified" << std::endl;
6470 return EINVAL;
6471 }
6472 if (bucket_name.empty()) {
6473 cerr << "ERROR: bucket not specified" << std::endl;
6474 return EINVAL;
6475 }
6476 rgw_bucket bucket;
6477 int ret = init_bucket_for_sync(tenant, bucket_name, bucket_id, bucket);
6478 if (ret < 0) {
6479 return -ret;
6480 }
6481 RGWBucketSyncStatusManager sync(store, source_zone, bucket);
6482
6483 ret = sync.init();
6484 if (ret < 0) {
6485 cerr << "ERROR: sync.init() returned ret=" << ret << std::endl;
6486 return -ret;
6487 }
6488
6489 ret = sync.run();
6490 if (ret < 0) {
6491 cerr << "ERROR: sync.run() returned ret=" << ret << std::endl;
6492 return -ret;
6493 }
6494 }
6495
6496 if (opt_cmd == OPT_BILOG_LIST) {
6497 if (bucket_name.empty()) {
6498 cerr << "ERROR: bucket not specified" << std::endl;
6499 return EINVAL;
6500 }
6501 RGWBucketInfo bucket_info;
6502 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
6503 if (ret < 0) {
6504 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
6505 return -ret;
6506 }
6507 formatter->open_array_section("entries");
6508 bool truncated;
6509 int count = 0;
6510 if (max_entries < 0)
6511 max_entries = 1000;
6512
6513 do {
6514 list<rgw_bi_log_entry> entries;
6515 ret = store->list_bi_log_entries(bucket_info, shard_id, marker, max_entries - count, entries, &truncated);
6516 if (ret < 0) {
6517 cerr << "ERROR: list_bi_log_entries(): " << cpp_strerror(-ret) << std::endl;
6518 return -ret;
6519 }
6520
6521 count += entries.size();
6522
6523 for (list<rgw_bi_log_entry>::iterator iter = entries.begin(); iter != entries.end(); ++iter) {
6524 rgw_bi_log_entry& entry = *iter;
6525 encode_json("entry", entry, formatter);
6526
6527 marker = entry.id;
6528 }
6529 formatter->flush(cout);
6530 } while (truncated && count < max_entries);
6531
6532 formatter->close_section();
6533 formatter->flush(cout);
6534 }
6535
6536 if (opt_cmd == OPT_SYNC_ERROR_LIST) {
6537 if (max_entries < 0) {
6538 max_entries = 1000;
6539 }
6540
6541 bool truncated;
6542 utime_t start_time, end_time;
6543
6544 int ret = parse_date_str(start_date, start_time);
6545 if (ret < 0)
6546 return -ret;
6547
6548 ret = parse_date_str(end_date, end_time);
6549 if (ret < 0)
6550 return -ret;
6551
6552 if (shard_id < 0) {
6553 shard_id = 0;
6554 }
6555
6556 formatter->open_array_section("entries");
6557
6558 for (; shard_id < ERROR_LOGGER_SHARDS; ++shard_id) {
6559 formatter->open_object_section("shard");
6560 encode_json("shard_id", shard_id, formatter);
6561 formatter->open_array_section("entries");
6562
6563 int count = 0;
6564 string oid = RGWSyncErrorLogger::get_shard_oid(RGW_SYNC_ERROR_LOG_SHARD_PREFIX, shard_id);
6565
6566 do {
6567 list<cls_log_entry> entries;
6568 ret = store->time_log_list(oid, start_time.to_real_time(), end_time.to_real_time(),
6569 max_entries - count, entries, marker, &marker, &truncated);
6570 if (ret == -ENOENT) {
6571 break;
6572 }
6573 if (ret < 0) {
6574 cerr << "ERROR: store->time_log_list(): " << cpp_strerror(-ret) << std::endl;
6575 return -ret;
6576 }
6577
6578 count += entries.size();
6579
6580 for (auto& cls_entry : entries) {
6581 rgw_sync_error_info log_entry;
6582
6583 auto iter = cls_entry.data.begin();
6584 try {
6585 ::decode(log_entry, iter);
6586 } catch (buffer::error& err) {
6587 cerr << "ERROR: failed to decode log entry" << std::endl;
6588 continue;
6589 }
6590 formatter->open_object_section("entry");
6591 encode_json("id", cls_entry.id, formatter);
6592 encode_json("section", cls_entry.section, formatter);
6593 encode_json("name", cls_entry.name, formatter);
6594 encode_json("timestamp", cls_entry.timestamp, formatter);
6595 encode_json("info", log_entry, formatter);
6596 formatter->close_section();
6597 formatter->flush(cout);
6598 }
6599 } while (truncated && count < max_entries);
6600
6601 formatter->close_section();
6602 formatter->close_section();
6603
6604 if (specified_shard_id) {
6605 break;
6606 }
6607 }
6608
6609 formatter->close_section();
6610 formatter->flush(cout);
6611 }
6612
6613 if (opt_cmd == OPT_BILOG_TRIM) {
6614 if (bucket_name.empty()) {
6615 cerr << "ERROR: bucket not specified" << std::endl;
6616 return EINVAL;
6617 }
6618 RGWBucketInfo bucket_info;
6619 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
6620 if (ret < 0) {
6621 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
6622 return -ret;
6623 }
6624 ret = store->trim_bi_log_entries(bucket_info, shard_id, start_marker, end_marker);
6625 if (ret < 0) {
6626 cerr << "ERROR: trim_bi_log_entries(): " << cpp_strerror(-ret) << std::endl;
6627 return -ret;
6628 }
6629 }
6630
6631 if (opt_cmd == OPT_BILOG_STATUS) {
6632 if (bucket_name.empty()) {
6633 cerr << "ERROR: bucket not specified" << std::endl;
6634 return EINVAL;
6635 }
6636 RGWBucketInfo bucket_info;
6637 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
6638 if (ret < 0) {
6639 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
6640 return -ret;
6641 }
6642 map<int, string> markers;
6643 ret = store->get_bi_log_status(bucket_info, shard_id, markers);
6644 if (ret < 0) {
6645 cerr << "ERROR: trim_bi_log_entries(): " << cpp_strerror(-ret) << std::endl;
6646 return -ret;
6647 }
6648 formatter->open_object_section("entries");
6649 encode_json("markers", markers, formatter);
6650 formatter->close_section();
6651 formatter->flush(cout);
6652 }
6653
6654 if (opt_cmd == OPT_DATALOG_LIST) {
6655 formatter->open_array_section("entries");
6656 bool truncated;
6657 int count = 0;
6658 if (max_entries < 0)
6659 max_entries = 1000;
6660
6661 utime_t start_time, end_time;
6662
6663 int ret = parse_date_str(start_date, start_time);
6664 if (ret < 0)
6665 return -ret;
6666
6667 ret = parse_date_str(end_date, end_time);
6668 if (ret < 0)
6669 return -ret;
6670
6671 RGWDataChangesLog *log = store->data_log;
6672 RGWDataChangesLog::LogMarker marker;
6673
6674 do {
6675 list<rgw_data_change_log_entry> entries;
6676 ret = log->list_entries(start_time.to_real_time(), end_time.to_real_time(), max_entries - count, entries, marker, &truncated);
6677 if (ret < 0) {
6678 cerr << "ERROR: list_bi_log_entries(): " << cpp_strerror(-ret) << std::endl;
6679 return -ret;
6680 }
6681
6682 count += entries.size();
6683
6684 for (list<rgw_data_change_log_entry>::iterator iter = entries.begin(); iter != entries.end(); ++iter) {
6685 rgw_data_change_log_entry& entry = *iter;
6686 if (!extra_info) {
6687 encode_json("entry", entry.entry, formatter);
6688 } else {
6689 encode_json("entry", entry, formatter);
6690 }
6691 }
6692 formatter->flush(cout);
6693 } while (truncated && count < max_entries);
6694
6695 formatter->close_section();
6696 formatter->flush(cout);
6697 }
6698
6699 if (opt_cmd == OPT_DATALOG_STATUS) {
6700 RGWDataChangesLog *log = store->data_log;
6701 int i = (specified_shard_id ? shard_id : 0);
6702
6703 formatter->open_array_section("entries");
6704 for (; i < g_ceph_context->_conf->rgw_data_log_num_shards; i++) {
6705 list<cls_log_entry> entries;
6706
6707 RGWDataChangesLogInfo info;
6708 log->get_info(i, &info);
6709
6710 ::encode_json("info", info, formatter);
6711
6712 if (specified_shard_id)
6713 break;
6714 }
6715
6716 formatter->close_section();
6717 formatter->flush(cout);
6718 }
6719
6720 if (opt_cmd == OPT_DATALOG_TRIM) {
6721 utime_t start_time, end_time;
6722
6723 int ret = parse_date_str(start_date, start_time);
6724 if (ret < 0)
6725 return -ret;
6726
6727 ret = parse_date_str(end_date, end_time);
6728 if (ret < 0)
6729 return -ret;
6730
6731 RGWDataChangesLog *log = store->data_log;
6732 ret = log->trim_entries(start_time.to_real_time(), end_time.to_real_time(), start_marker, end_marker);
6733 if (ret < 0) {
6734 cerr << "ERROR: trim_entries(): " << cpp_strerror(-ret) << std::endl;
6735 return -ret;
6736 }
6737 }
6738
6739 if (opt_cmd == OPT_OPSTATE_LIST) {
6740 RGWOpState oc(store);
6741
6742 int max = 1000;
6743
6744 void *handle;
6745 oc.init_list_entries(client_id, op_id, object, &handle);
6746 list<cls_statelog_entry> entries;
6747 bool done;
6748 formatter->open_array_section("entries");
6749 do {
6750 int ret = oc.list_entries(handle, max, entries, &done);
6751 if (ret < 0) {
6752 cerr << "oc.list_entries returned " << cpp_strerror(-ret) << std::endl;
6753 oc.finish_list_entries(handle);
6754 return -ret;
6755 }
6756
6757 for (list<cls_statelog_entry>::iterator iter = entries.begin(); iter != entries.end(); ++iter) {
6758 oc.dump_entry(*iter, formatter);
6759 }
6760
6761 formatter->flush(cout);
6762 } while (!done);
6763 formatter->close_section();
6764 formatter->flush(cout);
6765 oc.finish_list_entries(handle);
6766 }
6767
6768 if (opt_cmd == OPT_OPSTATE_SET || opt_cmd == OPT_OPSTATE_RENEW) {
6769 RGWOpState oc(store);
6770
6771 RGWOpState::OpState state;
6772 if (object.empty() || client_id.empty() || op_id.empty()) {
6773 cerr << "ERROR: need to specify client_id, op_id, and object" << std::endl;
6774 return EINVAL;
6775 }
6776 if (state_str.empty()) {
6777 cerr << "ERROR: state was not specified" << std::endl;
6778 return EINVAL;
6779 }
6780 int ret = oc.state_from_str(state_str, &state);
6781 if (ret < 0) {
6782 cerr << "ERROR: invalid state: " << state_str << std::endl;
6783 return -ret;
6784 }
6785
6786 if (opt_cmd == OPT_OPSTATE_SET) {
6787 ret = oc.set_state(client_id, op_id, object, state);
6788 if (ret < 0) {
6789 cerr << "ERROR: failed to set state: " << cpp_strerror(-ret) << std::endl;
6790 return -ret;
6791 }
6792 } else {
6793 ret = oc.renew_state(client_id, op_id, object, state);
6794 if (ret < 0) {
6795 cerr << "ERROR: failed to renew state: " << cpp_strerror(-ret) << std::endl;
6796 return -ret;
6797 }
6798 }
6799 }
6800 if (opt_cmd == OPT_OPSTATE_RM) {
6801 RGWOpState oc(store);
6802
6803 if (object.empty() || client_id.empty() || op_id.empty()) {
6804 cerr << "ERROR: need to specify client_id, op_id, and object" << std::endl;
6805 return EINVAL;
6806 }
6807 ret = oc.remove_entry(client_id, op_id, object);
6808 if (ret < 0) {
6809 cerr << "ERROR: failed to set state: " << cpp_strerror(-ret) << std::endl;
6810 return -ret;
6811 }
6812 }
6813
6814 if (opt_cmd == OPT_REPLICALOG_GET || opt_cmd == OPT_REPLICALOG_UPDATE ||
6815 opt_cmd == OPT_REPLICALOG_DELETE) {
6816 if (replica_log_type_str.empty()) {
6817 cerr << "ERROR: need to specify --replica-log-type=<metadata | data | bucket>" << std::endl;
6818 return EINVAL;
6819 }
6820 }
6821
6822 if (opt_cmd == OPT_REPLICALOG_GET) {
6823 RGWReplicaBounds bounds;
6824 if (replica_log_type == ReplicaLog_Metadata) {
6825 if (!specified_shard_id) {
6826 cerr << "ERROR: shard-id must be specified for get operation" << std::endl;
6827 return EINVAL;
6828 }
6829
6830 RGWReplicaObjectLogger logger(store, pool, META_REPLICA_LOG_OBJ_PREFIX);
6831 int ret = logger.get_bounds(shard_id, bounds);
6832 if (ret < 0)
6833 return -ret;
6834 } else if (replica_log_type == ReplicaLog_Data) {
6835 if (!specified_shard_id) {
6836 cerr << "ERROR: shard-id must be specified for get operation" << std::endl;
6837 return EINVAL;
6838 }
6839 RGWReplicaObjectLogger logger(store, pool, DATA_REPLICA_LOG_OBJ_PREFIX);
6840 int ret = logger.get_bounds(shard_id, bounds);
6841 if (ret < 0)
6842 return -ret;
6843 } else if (replica_log_type == ReplicaLog_Bucket) {
6844 if (bucket_name.empty()) {
6845 cerr << "ERROR: bucket not specified" << std::endl;
6846 return EINVAL;
6847 }
6848 RGWBucketInfo bucket_info;
6849 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
6850 if (ret < 0) {
6851 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
6852 return -ret;
6853 }
6854
6855 RGWReplicaBucketLogger logger(store);
6856 ret = logger.get_bounds(bucket, shard_id, bounds);
6857 if (ret < 0)
6858 return -ret;
6859 } else { // shouldn't get here
6860 ceph_abort();
6861 }
6862 encode_json("bounds", bounds, formatter);
6863 formatter->flush(cout);
6864 cout << std::endl;
6865 }
6866
6867 if (opt_cmd == OPT_REPLICALOG_DELETE) {
6868 if (replica_log_type == ReplicaLog_Metadata) {
6869 if (!specified_shard_id) {
6870 cerr << "ERROR: shard-id must be specified for delete operation" << std::endl;
6871 return EINVAL;
6872 }
6873 if (!specified_daemon_id) {
6874 cerr << "ERROR: daemon-id must be specified for delete operation" << std::endl;
6875 return EINVAL;
6876 }
6877 RGWReplicaObjectLogger logger(store, pool, META_REPLICA_LOG_OBJ_PREFIX);
6878 int ret = logger.delete_bound(shard_id, daemon_id, false);
6879 if (ret < 0)
6880 return -ret;
6881 } else if (replica_log_type == ReplicaLog_Data) {
6882 if (!specified_shard_id) {
6883 cerr << "ERROR: shard-id must be specified for delete operation" << std::endl;
6884 return EINVAL;
6885 }
6886 if (!specified_daemon_id) {
6887 cerr << "ERROR: daemon-id must be specified for delete operation" << std::endl;
6888 return EINVAL;
6889 }
6890 RGWReplicaObjectLogger logger(store, pool, DATA_REPLICA_LOG_OBJ_PREFIX);
6891 int ret = logger.delete_bound(shard_id, daemon_id, false);
6892 if (ret < 0)
6893 return -ret;
6894 } else if (replica_log_type == ReplicaLog_Bucket) {
6895 if (bucket_name.empty()) {
6896 cerr << "ERROR: bucket not specified" << std::endl;
6897 return EINVAL;
6898 }
6899 RGWBucketInfo bucket_info;
6900 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
6901 if (ret < 0) {
6902 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
6903 return -ret;
6904 }
6905
6906 RGWReplicaBucketLogger logger(store);
6907 ret = logger.delete_bound(bucket, shard_id, daemon_id, false);
6908 if (ret < 0)
6909 return -ret;
6910 }
6911 }
6912
6913 if (opt_cmd == OPT_REPLICALOG_UPDATE) {
6914 if (marker.empty()) {
6915 cerr << "ERROR: marker was not specified" <<std::endl;
6916 return EINVAL;
6917 }
6918 utime_t time = ceph_clock_now();
6919 if (!date.empty()) {
6920 ret = parse_date_str(date, time);
6921 if (ret < 0) {
6922 cerr << "ERROR: failed to parse start date" << std::endl;
6923 return EINVAL;
6924 }
6925 }
6926 list<RGWReplicaItemMarker> entries;
6927 int ret = read_decode_json(infile, entries);
6928 if (ret < 0) {
6929 cerr << "ERROR: failed to decode entries" << std::endl;
6930 return EINVAL;
6931 }
6932 RGWReplicaBounds bounds;
6933 if (replica_log_type == ReplicaLog_Metadata) {
6934 if (!specified_shard_id) {
6935 cerr << "ERROR: shard-id must be specified for get operation" << std::endl;
6936 return EINVAL;
6937 }
6938
6939 RGWReplicaObjectLogger logger(store, pool, META_REPLICA_LOG_OBJ_PREFIX);
6940 int ret = logger.update_bound(shard_id, daemon_id, marker, time, &entries);
6941 if (ret < 0) {
6942 cerr << "ERROR: failed to update bounds: " << cpp_strerror(-ret) << std::endl;
6943 return -ret;
6944 }
6945 } else if (replica_log_type == ReplicaLog_Data) {
6946 if (!specified_shard_id) {
6947 cerr << "ERROR: shard-id must be specified for get operation" << std::endl;
6948 return EINVAL;
6949 }
6950 RGWReplicaObjectLogger logger(store, pool, DATA_REPLICA_LOG_OBJ_PREFIX);
6951 int ret = logger.update_bound(shard_id, daemon_id, marker, time, &entries);
6952 if (ret < 0) {
6953 cerr << "ERROR: failed to update bounds: " << cpp_strerror(-ret) << std::endl;
6954 return -ret;
6955 }
6956 } else if (replica_log_type == ReplicaLog_Bucket) {
6957 if (bucket_name.empty()) {
6958 cerr << "ERROR: bucket not specified" << std::endl;
6959 return EINVAL;
6960 }
6961 RGWBucketInfo bucket_info;
6962 int ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket);
6963 if (ret < 0) {
6964 cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
6965 return -ret;
6966 }
6967
6968 RGWReplicaBucketLogger logger(store);
6969 ret = logger.update_bound(bucket, shard_id, daemon_id, marker, time, &entries);
6970 if (ret < 0) {
6971 cerr << "ERROR: failed to update bounds: " << cpp_strerror(-ret) << std::endl;
6972 return -ret;
6973 }
6974 }
6975 }
6976
6977 bool quota_op = (opt_cmd == OPT_QUOTA_SET || opt_cmd == OPT_QUOTA_ENABLE || opt_cmd == OPT_QUOTA_DISABLE);
6978
6979 if (quota_op) {
6980 if (bucket_name.empty() && user_id.empty()) {
6981 cerr << "ERROR: bucket name or uid is required for quota operation" << std::endl;
6982 return EINVAL;
6983 }
6984
6985 if (!bucket_name.empty()) {
6986 if (!quota_scope.empty() && quota_scope != "bucket") {
6987 cerr << "ERROR: invalid quota scope specification." << std::endl;
6988 return EINVAL;
6989 }
6990 set_bucket_quota(store, opt_cmd, tenant, bucket_name,
6991 max_size, max_objects, have_max_size, have_max_objects);
6992 } else if (!user_id.empty()) {
6993 if (quota_scope == "bucket") {
6994 set_user_bucket_quota(opt_cmd, user, user_op, max_size, max_objects, have_max_size, have_max_objects);
6995 } else if (quota_scope == "user") {
6996 set_user_quota(opt_cmd, user, user_op, max_size, max_objects, have_max_size, have_max_objects);
6997 } else {
6998 cerr << "ERROR: invalid quota scope specification. Please specify either --quota-scope=bucket, or --quota-scope=user" << std::endl;
6999 return EINVAL;
7000 }
7001 }
7002 }
7003
7004 return 0;
7005 }