]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_sync_policy.h
import ceph 15.2.10
[ceph.git] / ceph / src / rgw / rgw_sync_policy.h
CommitLineData
9f95a23c
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4/*
5 * Ceph - scalable distributed file system
6 *
7 * Copyright (C) 2018 Red Hat, Inc.
8 *
9 * This is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License version 2.1, as published by the Free Software
12 * Foundation. See file COPYING.
13 *
14 */
15
16#pragma once
17
18#include "rgw_basic_types.h"
19
20
21struct rgw_sync_symmetric_group {
22 string id;
23 std::set<rgw_zone_id> zones;
24
25 rgw_sync_symmetric_group() {}
26 rgw_sync_symmetric_group(const string& _id,
27 const std::set<rgw_zone_id> _zones) : id(_id), zones(_zones) {}
28
29
30 void encode(bufferlist& bl) const {
31 ENCODE_START(1, 1, bl);
32 encode(id, bl);
33 encode(zones, bl);
34 ENCODE_FINISH(bl);
35 }
36
37 void decode(bufferlist::const_iterator& bl) {
38 DECODE_START(1, bl);
39 decode(id, bl);
40 decode(zones, bl);
41 DECODE_FINISH(bl);
42 }
43
44 void dump(ceph::Formatter *f) const;
45 void decode_json(JSONObj *obj);
46};
47WRITE_CLASS_ENCODER(rgw_sync_symmetric_group)
48
49struct rgw_sync_directional_rule {
50 rgw_zone_id source_zone;
51 rgw_zone_id dest_zone;
52
53 void encode(bufferlist& bl) const {
54 ENCODE_START(1, 1, bl);
55 encode(source_zone, bl);
56 encode(dest_zone, bl);
57 ENCODE_FINISH(bl);
58 }
59
60 void decode(bufferlist::const_iterator& bl) {
61 DECODE_START(1, bl);
62 decode(source_zone, bl);
63 decode(dest_zone, bl);
64 DECODE_FINISH(bl);
65 }
66
67 void dump(ceph::Formatter *f) const;
68 void decode_json(JSONObj *obj);
69};
70WRITE_CLASS_ENCODER(rgw_sync_directional_rule)
71
72struct rgw_sync_bucket_entity {
73 std::optional<rgw_zone_id> zone; /* define specific zones */
74 std::optional<rgw_bucket> bucket; /* define specific bucket */
75
76 static bool match_str(const string& s1, const string& s2) { /* empty string is wildcard */
77 return (s1.empty() ||
78 s2.empty() ||
79 s1 == s2);
80 }
81
82 bool all_zones{false};
83
84 rgw_sync_bucket_entity() {}
85 rgw_sync_bucket_entity(const rgw_zone_id& _zone,
86 std::optional<rgw_bucket> _bucket) : zone(_zone),
87 bucket(_bucket.value_or(rgw_bucket())) {}
88
89 bool specific() const {
90 return zone && bucket;
91 }
92
93 void encode(bufferlist& bl) const {
94 ENCODE_START(1, 1, bl);
95 encode(all_zones, bl);
96 encode(zone, bl);
97 encode(bucket, bl);
98 ENCODE_FINISH(bl);
99 }
100
101 void decode(bufferlist::const_iterator& bl) {
102 DECODE_START(1, bl);
103 decode(all_zones, bl);
104 decode(zone, bl);
105 decode(bucket, bl);
106 DECODE_FINISH(bl);
107 }
108
109 void dump(ceph::Formatter *f) const;
110 void decode_json(JSONObj *obj);
111
112 rgw_bucket get_bucket() const {
113 return bucket.value_or(rgw_bucket());
114 }
115
116 string bucket_key() const;
117
118 bool match_zone(const rgw_zone_id& z) const {
119 if (all_zones) {
120 return true;
121 }
122 if (!zone) {
123 return false;
124 }
125
126 return (*zone == z);
127 }
128
129 void apply_zone(const rgw_zone_id& z) {
130 all_zones = false;
131 zone = z;
132 }
133
134 static bool match_bucket_id(const string& bid1, const string& bid2) {
135 return (bid1.empty() || bid2.empty() || (bid1 == bid2));
136 }
137
138 bool match_bucket(std::optional<rgw_bucket> b) const {
139 if (!b) {
140 return true;
141 }
142
143 if (!bucket) {
144 return true;
145 }
146
147 return (match_str(bucket->tenant, b->tenant) &&
148 match_str(bucket->name, b->name) &&
149 match_bucket_id(bucket->bucket_id, b->bucket_id));
150 }
151
152 bool match(const rgw_sync_bucket_entity& entity) const {
153 if (!entity.zone) {
154 return match_bucket(entity.bucket);
155 }
156 return (match_zone(*entity.zone) && match_bucket(entity.bucket));
157 }
158
159 const bool operator<(const rgw_sync_bucket_entity& e) const {
160 if (all_zones && !e.all_zones) {
161 return false;
162 }
163 if (!all_zones && e.all_zones) {
164 return true;
165 }
166 if (zone < e.zone) {
167 return true;
168 }
169 if (e.zone < zone) {
170 return false;
171 }
172 return (bucket < e.bucket);
173 }
174
175 void apply_bucket(std::optional<rgw_bucket> _b);
176};
177WRITE_CLASS_ENCODER(rgw_sync_bucket_entity)
178
179struct rgw_sync_pipe_filter_tag {
180 string key;
181 string value;
182
183 rgw_sync_pipe_filter_tag() {}
184 rgw_sync_pipe_filter_tag(const string& s) {
185 from_str(s);
186 }
187 rgw_sync_pipe_filter_tag(const string& _key,
188 const string& _value) : key(_key),
189 value(_value) {}
190
191 void encode(bufferlist& bl) const {
192 ENCODE_START(1, 1, bl);
193 encode(key, bl);
194 encode(value, bl);
195 ENCODE_FINISH(bl);
196 }
197
198 void decode(bufferlist::const_iterator& bl) {
199 DECODE_START(1, bl);
200 decode(key, bl);
201 decode(value, bl);
202 DECODE_FINISH(bl);
203 }
204
205 void dump(ceph::Formatter *f) const;
206 void decode_json(JSONObj *obj);
207
208 bool from_str(const string& s);
209
210 bool operator<(const rgw_sync_pipe_filter_tag& t) const {
211 if (key < t.key) {
212 return true;
213 }
214 if (t.key < key) {
215 return false;
216 }
217 return (value < t.value);
218 }
219
220 bool operator==(const string& s) const;
221};
222WRITE_CLASS_ENCODER(rgw_sync_pipe_filter_tag)
223
224struct rgw_sync_pipe_filter {
225 std::optional<string> prefix;
226 std::set<rgw_sync_pipe_filter_tag> tags;
227
228 void set_prefix(std::optional<std::string> opt_prefix,
229 bool prefix_rm);
230 void set_tags(std::list<std::string>& tags_add,
231 std::list<std::string>& tags_rm);
232
233 void encode(bufferlist& bl) const;
234 void decode(bufferlist::const_iterator& bl);
235
236 void dump(ceph::Formatter *f) const;
237 void decode_json(JSONObj *obj);
238
239 bool is_subset_of(const rgw_sync_pipe_filter& f) const;
240
241 bool has_tags() const;
242 bool check_tag(const string& s) const;
243 bool check_tag(const string& k, const string& v) const;
244 bool check_tags(const std::vector<string>& tags) const;
245 bool check_tags(const RGWObjTags::tag_map_t& tags) const;
246};
247WRITE_CLASS_ENCODER(rgw_sync_pipe_filter)
248
249struct rgw_sync_pipe_acl_translation {
250 rgw_user owner;
251
252 void encode(bufferlist& bl) const {
253 ENCODE_START(1, 1, bl);
254 encode(owner, bl);
255 ENCODE_FINISH(bl);
256 }
257
258 void decode(bufferlist::const_iterator& bl) {
259 DECODE_START(1, bl);
260 decode(owner, bl);
261 DECODE_FINISH(bl);
262 }
263
264 void dump(ceph::Formatter *f) const;
265 void decode_json(JSONObj *obj);
266
267 bool operator==(const rgw_sync_pipe_acl_translation& aclt) const {
268 return (owner == aclt.owner);
269 }
270};
271WRITE_CLASS_ENCODER(rgw_sync_pipe_acl_translation)
272
273struct rgw_sync_pipe_source_params {
274 rgw_sync_pipe_filter filter;
275
276 void encode(bufferlist& bl) const {
277 ENCODE_START(1, 1, bl);
278 encode(filter, bl);
279 ENCODE_FINISH(bl);
280 }
281
282 void decode(bufferlist::const_iterator& bl) {
283 DECODE_START(1, bl);
284 decode(filter, bl);
285 DECODE_FINISH(bl);
286 }
287
288 void dump(ceph::Formatter *f) const;
289 void decode_json(JSONObj *obj);
290};
291WRITE_CLASS_ENCODER(rgw_sync_pipe_source_params)
292
293struct rgw_sync_pipe_dest_params {
294 std::optional<rgw_sync_pipe_acl_translation> acl_translation;
295 std::optional<string> storage_class;
296
297 void encode(bufferlist& bl) const {
298 ENCODE_START(1, 1, bl);
299 encode(acl_translation, bl);
300 encode(storage_class, bl);
301 ENCODE_FINISH(bl);
302 }
303
304 void decode(bufferlist::const_iterator& bl) {
305 DECODE_START(1, bl);
306 decode(acl_translation, bl);
307 decode(storage_class, bl);
308 DECODE_FINISH(bl);
309 }
310
311 void set_storage_class(const string& sc) {
312 storage_class = sc;
313 }
314
315 void set_owner(const rgw_user& owner) {
316 if (owner.empty()){
317 acl_translation.reset();
318 } else {
319 acl_translation.emplace();
320 acl_translation->owner = owner;
321 }
322 }
323
324 void dump(ceph::Formatter *f) const;
325 void decode_json(JSONObj *obj);
326
327 bool operator==(const rgw_sync_pipe_dest_params& rhs) const {
328 return (acl_translation == rhs.acl_translation &&
329 storage_class == rhs.storage_class);
330 }
331};
332WRITE_CLASS_ENCODER(rgw_sync_pipe_dest_params)
333
334struct rgw_sync_pipe_params {
335 rgw_sync_pipe_source_params source;
336 rgw_sync_pipe_dest_params dest;
337 enum Mode {
338 MODE_SYSTEM = 0,
339 MODE_USER = 1,
340 } mode{MODE_SYSTEM};
341 int32_t priority{0};
342 rgw_user user;
343
344 void encode(bufferlist& bl) const {
345 ENCODE_START(1, 1, bl);
346 encode(source, bl);
347 encode(dest, bl);
348 encode(priority, bl);
349 encode((uint8_t)mode, bl);
350 encode(user, bl);
351 ENCODE_FINISH(bl);
352 }
353
354 void decode(bufferlist::const_iterator& bl) {
355 DECODE_START(1, bl);
356 decode(source, bl);
357 decode(dest, bl);
358 decode(priority, bl);
359 uint8_t m;
360 decode(m, bl);
361 mode = (Mode)m;
362 decode(user, bl);
363 DECODE_FINISH(bl);
364 }
365
366 void dump(ceph::Formatter *f) const;
367 void decode_json(JSONObj *obj);
368};
369WRITE_CLASS_ENCODER(rgw_sync_pipe_params)
370
371struct rgw_sync_bucket_pipe {
372 string id;
373 rgw_sync_bucket_entity source;
374 rgw_sync_bucket_entity dest;
375
376 rgw_sync_pipe_params params;
377
378 bool specific() const {
379 return source.specific() && dest.specific();
380 }
381
382 void encode(bufferlist& bl) const {
383 ENCODE_START(1, 1, bl);
384 encode(id, bl);
385 encode(source, bl);
386 encode(dest, bl);
387 encode(params, bl);
388 ENCODE_FINISH(bl);
389 }
390
391 void decode(bufferlist::const_iterator& bl) {
392 DECODE_START(1, bl);
393 decode(id, bl);
394 decode(source, bl);
395 decode(dest, bl);
396 decode(params, bl);
397 DECODE_FINISH(bl);
398 }
399
400 const bool operator<(const rgw_sync_bucket_pipe& p) const {
401 if (id < p.id) {
402 return true;
403 }
404 if (id >p.id) {
405 return false;
406 }
407 if (source < p.source) {
408 return true;
409 }
410 if (p.source < source) {
411 return false;
412 }
413 return (dest < p.dest);
414 }
415
416 void dump(ceph::Formatter *f) const;
417 void decode_json(JSONObj *obj);
418};
419WRITE_CLASS_ENCODER(rgw_sync_bucket_pipe)
420
421struct rgw_sync_bucket_entities {
422 std::optional<rgw_bucket> bucket; /* define specific bucket */
423 std::optional<std::set<rgw_zone_id> > zones; /* define specific zones, if not set then all zones */
424
425 bool all_zones{false};
426
427
428 void encode(bufferlist& bl) const {
429 ENCODE_START(1, 1, bl);
430 encode(bucket, bl);
431 encode(zones, bl);
432 encode(all_zones, bl);
433 ENCODE_FINISH(bl);
434 }
435
436 void decode(bufferlist::const_iterator& bl) {
437 DECODE_START(1, bl);
438 decode(bucket, bl);
439 decode(zones, bl);
440 decode(all_zones, bl);
441 DECODE_FINISH(bl);
442 }
443
444 void dump(ceph::Formatter *f) const;
445 void decode_json(JSONObj *obj);
446
447 bool match_bucket(std::optional<rgw_bucket> b) const {
448 if (!b) {
449 return true;
450 }
451
452 if (!bucket) {
453 return true;
454 }
455
456 return (rgw_sync_bucket_entity::match_str(bucket->tenant, b->tenant) &&
457 rgw_sync_bucket_entity::match_str(bucket->name, b->name) &&
458 rgw_sync_bucket_entity::match_str(bucket->bucket_id, b->bucket_id));
459 }
460
461 void add_zones(const std::vector<rgw_zone_id>& new_zones);
462 void remove_zones(const std::vector<rgw_zone_id>& rm_zones);
463 void set_bucket(std::optional<string> tenant,
464 std::optional<string> bucket_name,
465 std::optional<string> bucket_id);
466 void remove_bucket(std::optional<string> tenant,
467 std::optional<string> bucket_name,
468 std::optional<string> bucket_id);
469
470 bool match_zone(const rgw_zone_id& zone) const {
471 if (!zones) {
472 if (all_zones) {
473 return true;
474 }
475 return false;
476 }
477
478 return (zones->find(zone) != zones->end());
479 }
480
481 std::vector<rgw_sync_bucket_entity> expand() const;
482
483 rgw_bucket get_bucket() const {
484 return bucket.value_or(rgw_bucket());
485 }
486
487 static string bucket_key(std::optional<rgw_bucket> b);
488
489 void set_all_zones(bool state) {
490 all_zones = state;
491 if (all_zones) {
492 zones.reset();
493 }
494 }
495};
496WRITE_CLASS_ENCODER(rgw_sync_bucket_entities)
497
498struct rgw_sync_bucket_pipes {
499 string id;
500 rgw_sync_bucket_entities source;
501 rgw_sync_bucket_entities dest;
502
503 rgw_sync_pipe_params params;
504
505 void encode(bufferlist& bl) const {
506 ENCODE_START(1, 1, bl);
507 encode(id, bl);
508 encode(source, bl);
509 encode(dest, bl);
510 encode(params, bl);
511 ENCODE_FINISH(bl);
512 }
513
514 void decode(bufferlist::const_iterator& bl) {
515 DECODE_START(1, bl);
516 decode(id, bl);
517 decode(source, bl);
518 decode(dest, bl);
519 decode(params, bl);
520 DECODE_FINISH(bl);
521 }
522
523 bool match_source(const rgw_zone_id& zone, std::optional<rgw_bucket> b) const {
524 return (source.match_zone(zone) && source.match_bucket(b));
525 }
526
527 bool match_dest(const rgw_zone_id& zone, std::optional<rgw_bucket> b) const {
528 return (dest.match_zone(zone) && dest.match_bucket(b));
529 }
530
531 bool contains_zone_bucket(const rgw_zone_id& zone, std::optional<rgw_bucket> b) const {
532 return (match_source(zone, b) || match_dest(zone, b));
533 }
534
535 void dump(ceph::Formatter *f) const;
536 void decode_json(JSONObj *obj);
537
538 std::vector<rgw_sync_bucket_pipe> expand() const;
539
540 void get_potential_related_buckets(const rgw_bucket& bucket,
541 std::set<rgw_bucket> *sources,
542 std::set<rgw_bucket> *dests) const;
543};
544WRITE_CLASS_ENCODER(rgw_sync_bucket_pipes)
545
546std::ostream& operator<<(std::ostream& os, const rgw_sync_bucket_entity& e);
547std::ostream& operator<<(std::ostream& os, const rgw_sync_bucket_pipe& pipe);
548std::ostream& operator<<(std::ostream& os, const rgw_sync_bucket_entities& e);
549std::ostream& operator<<(std::ostream& os, const rgw_sync_bucket_pipes& pipe);
550
551/*
552 * define data flow between zones. Symmetrical: zones sync from each other.
553 * Directional: one zone fetches data from another.
554 */
555struct rgw_sync_data_flow_group {
556 std::vector<rgw_sync_symmetric_group> symmetrical;
557 std::vector<rgw_sync_directional_rule> directional;
558
559 void encode(bufferlist& bl) const {
560 ENCODE_START(1, 1, bl);
561 encode(symmetrical, bl);
562 encode(directional, bl);
563 ENCODE_FINISH(bl);
564 }
565
566 void decode(bufferlist::const_iterator& bl) {
567 DECODE_START(1, bl);
568 decode(symmetrical, bl);
569 decode(directional, bl);
570 DECODE_FINISH(bl);
571 }
572
573 void dump(ceph::Formatter *f) const;
574 void decode_json(JSONObj *obj);
575
576 bool empty() const {
577 return (symmetrical.empty() && directional.empty());
578 }
579
580 bool find_or_create_symmetrical(const string& flow_id, rgw_sync_symmetric_group **flow_group);
581 void remove_symmetrical(const string& flow_id, std::optional<std::vector<rgw_zone_id> > zones);
582 bool find_or_create_directional(const rgw_zone_id& source_zone, const rgw_zone_id& dest_zone, rgw_sync_directional_rule **flow_group);
583 void remove_directional(const rgw_zone_id& source_zone, const rgw_zone_id& dest_zone);
584
585 void init_default(const std::set<rgw_zone_id>& zones);
586};
587WRITE_CLASS_ENCODER(rgw_sync_data_flow_group)
588
589
590struct rgw_sync_policy_group {
591 string id;
592
593 rgw_sync_data_flow_group data_flow; /* override data flow, howver, will not be able to
594 add new flows that don't exist at higher level */
595 std::vector<rgw_sync_bucket_pipes> pipes; /* if not defined then applies to all
596 buckets (DR sync) */
597
598 enum Status {
599 UNKNOWN = 0, /* ? */
600 FORBIDDEN = 1, /* sync not allowed */
601 ALLOWED = 2, /* sync allowed */
602 ENABLED = 3, /* sync should happen */
603 } status;
604
605 void encode(bufferlist& bl) const {
606 ENCODE_START(1, 1, bl);
607 encode(id, bl);
608 encode(data_flow, bl);
609 encode(pipes, bl);
610 encode((uint32_t)status, bl);
611 ENCODE_FINISH(bl);
612 }
613
614 void decode(bufferlist::const_iterator& bl) {
615 DECODE_START(1, bl);
616 decode(id, bl);
617 decode(data_flow, bl);
618 decode(pipes, bl);
619 uint32_t s;
620 decode(s, bl);
621 status = (Status)s;
622 DECODE_FINISH(bl);
623 }
624
625 void dump(ceph::Formatter *f) const;
626 void decode_json(JSONObj *obj);
627
628 bool set_status(const string& s) {
629 if (s == "forbidden") {
630 status = rgw_sync_policy_group::Status::FORBIDDEN;
631 } else if (s == "allowed") {
632 status = rgw_sync_policy_group::Status::ALLOWED;
633 } else if (s == "enabled") {
634 status = rgw_sync_policy_group::Status::ENABLED;
635 } else {
636 status = rgw_sync_policy_group::Status::UNKNOWN;
637 return false;
638 }
639
640 return true;
641 }
642
643 bool find_pipe(const string& pipe_id, bool create, rgw_sync_bucket_pipes **pipe);
644 void remove_pipe(const string& pipe_id);
645
646 void get_potential_related_buckets(const rgw_bucket& bucket,
647 std::set<rgw_bucket> *sources,
648 std::set<rgw_bucket> *dests) const;
649
650};
651WRITE_CLASS_ENCODER(rgw_sync_policy_group)
652
653struct rgw_sync_policy_info {
654 std::map<string, rgw_sync_policy_group> groups;
655
656 void encode(bufferlist& bl) const {
657 ENCODE_START(1, 1, bl);
658 encode(groups, bl);
659 ENCODE_FINISH(bl);
660 }
661
662 void decode(bufferlist::const_iterator& bl) {
663 DECODE_START(1, bl);
664 decode(groups, bl);
665 DECODE_FINISH(bl);
666 }
667
668 void dump(ceph::Formatter *f) const;
669 void decode_json(JSONObj *obj);
670
671 bool empty() const {
672 return groups.empty();
673 }
674
675 void get_potential_related_buckets(const rgw_bucket& bucket,
676 std::set<rgw_bucket> *sources,
677 std::set<rgw_bucket> *dests) const;
678};
679WRITE_CLASS_ENCODER(rgw_sync_policy_info)
680
681