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