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