mirror of
https://github.com/ceph/ceph
synced 2025-03-21 17:57:38 +00:00
rgw: fix bucket suspension
This commit is contained in:
parent
f197e84517
commit
6752babdfd
@ -128,8 +128,7 @@ public:
|
||||
virtual int delete_bucket(std::string& id, rgw_bucket& bucket, bool remove_pool) = 0;
|
||||
virtual int purge_buckets(std::string& id, vector<rgw_bucket>& buckets) { return -ENOTSUP; }
|
||||
|
||||
virtual int disable_buckets(std::vector<rgw_bucket>& buckets) { return -ENOTSUP; }
|
||||
virtual int enable_buckets(std::vector<rgw_bucket>& buckets, uint64_t auid) { return -ENOTSUP; }
|
||||
virtual int set_buckets_enabled(std::vector<rgw_bucket>& buckets, bool enabled) { return -ENOTSUP; }
|
||||
virtual int bucket_suspended(rgw_bucket& bucket, bool *suspended) {
|
||||
*suspended = false;
|
||||
return 0;
|
||||
@ -271,6 +270,7 @@ public:
|
||||
/* The bucket here can either be the bucket name identifier, or the ID
|
||||
* in period format: ".123" */
|
||||
virtual int get_bucket_info(void *ctx, string& bucket, RGWBucketInfo& info) = 0;
|
||||
virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info) = 0;
|
||||
|
||||
|
||||
virtual int remove_temp_objects(string date, string time) {
|
||||
|
@ -1218,10 +1218,7 @@ int main(int argc, char **argv)
|
||||
RGWBucketEnt obj = iter->second;
|
||||
bucket_names.push_back(obj.bucket);
|
||||
}
|
||||
if (disable)
|
||||
ret = rgwstore->disable_buckets(bucket_names);
|
||||
else
|
||||
ret = rgwstore->enable_buckets(bucket_names, info.auid);
|
||||
ret = rgwstore->set_buckets_enabled(bucket_names, !disable);
|
||||
if (ret < 0) {
|
||||
cerr << "ERROR: failed to change pool" << std::endl;
|
||||
return 1;
|
||||
|
@ -430,24 +430,34 @@ inline ostream& operator<<(ostream& out, const rgw_bucket b) {
|
||||
|
||||
extern rgw_bucket rgw_root_bucket;
|
||||
|
||||
enum RGWBucketFlags {
|
||||
BUCKET_SUSPENDED = 0x1,
|
||||
};
|
||||
|
||||
struct RGWBucketInfo
|
||||
{
|
||||
rgw_bucket bucket;
|
||||
string owner;
|
||||
uint32_t flags;
|
||||
|
||||
void encode(bufferlist& bl) const {
|
||||
__u32 ver = 2;
|
||||
__u32 ver = 3;
|
||||
::encode(ver, bl);
|
||||
::encode(bucket, bl);
|
||||
::encode(owner, bl);
|
||||
::encode(flags, bl);
|
||||
}
|
||||
void decode(bufferlist::iterator& bl) {
|
||||
__u32 ver;
|
||||
::decode(ver, bl);
|
||||
::decode(bucket, bl);
|
||||
if (ver > 1)
|
||||
if (ver >= 2)
|
||||
::decode(owner, bl);
|
||||
if (ver >= 3)
|
||||
::decode(flags, bl);
|
||||
}
|
||||
|
||||
RGWBucketInfo() : flags(0) {}
|
||||
};
|
||||
WRITE_CLASS_ENCODER(RGWBucketInfo)
|
||||
|
||||
@ -545,12 +555,11 @@ struct RGWObjEnt {
|
||||
}
|
||||
};
|
||||
|
||||
/** Store basic data on an object */
|
||||
/** Store basic data on bucket */
|
||||
struct RGWBucketEnt {
|
||||
rgw_bucket bucket;
|
||||
size_t size;
|
||||
time_t mtime;
|
||||
string etag;
|
||||
uint64_t count;
|
||||
|
||||
void encode(bufferlist& bl) const {
|
||||
@ -583,7 +592,6 @@ struct RGWBucketEnt {
|
||||
bucket.clear();
|
||||
size = 0;
|
||||
mtime = 0;
|
||||
etag = "";
|
||||
count = 0;
|
||||
}
|
||||
};
|
||||
|
@ -667,3 +667,8 @@ int RGWFS::get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int RGWFS::put_bucket_info(string& bucket_name, RGWBucketInfo& info)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ public:
|
||||
int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime, map<string, bufferlist> *attrs);
|
||||
|
||||
virtual int get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info);
|
||||
virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -172,21 +172,16 @@ static int get_obj_attrs(struct req_state *s, rgw_obj& obj, map<string, bufferli
|
||||
return ret;
|
||||
}
|
||||
|
||||
int read_acls(struct req_state *s, RGWAccessControlPolicy *policy, rgw_bucket& bucket, string& object)
|
||||
static int read_acls(struct req_state *s, RGWBucketInfo& bucket_info, RGWAccessControlPolicy *policy, rgw_bucket& bucket, string& object)
|
||||
{
|
||||
string upload_id;
|
||||
url_decode(s->args.get("uploadId"), upload_id);
|
||||
string oid = object;
|
||||
rgw_obj obj;
|
||||
|
||||
if (!oid.empty()) {
|
||||
bool suspended;
|
||||
int ret = rgwstore->bucket_suspended(bucket, &suspended);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (suspended)
|
||||
return -ERR_USER_SUSPENDED;
|
||||
if (bucket_info.flags & BUCKET_SUSPENDED) {
|
||||
dout(0) << "bucket " << bucket_info.bucket.name << " is suspended" << dendl;
|
||||
return -ERR_USER_SUSPENDED;
|
||||
}
|
||||
|
||||
if (!oid.empty() && !upload_id.empty()) {
|
||||
@ -224,7 +219,7 @@ int read_acls(struct req_state *s, RGWAccessControlPolicy *policy, rgw_bucket& b
|
||||
* only_bucket: If true, reads the bucket ACL rather than the object ACL.
|
||||
* Returns: 0 on success, -ERR# otherwise.
|
||||
*/
|
||||
int read_acls(struct req_state *s, bool only_bucket)
|
||||
static int read_acls(struct req_state *s, bool only_bucket)
|
||||
{
|
||||
int ret = 0;
|
||||
string obj_str;
|
||||
@ -242,8 +237,8 @@ int read_acls(struct req_state *s, bool only_bucket)
|
||||
rgwstore->set_atomic(s->obj_ctx, obj);
|
||||
}
|
||||
|
||||
RGWBucketInfo bucket_info;
|
||||
if (s->bucket_name_str.size()) {
|
||||
RGWBucketInfo bucket_info;
|
||||
ret = rgwstore->get_bucket_info(s->obj_ctx, s->bucket_name_str, bucket_info);
|
||||
if (ret < 0) {
|
||||
dout(0) << "couldn't get bucket from bucket_name (name=" << s->bucket_name_str << ")" << dendl;
|
||||
@ -253,7 +248,7 @@ int read_acls(struct req_state *s, bool only_bucket)
|
||||
s->bucket_owner = bucket_info.owner;
|
||||
}
|
||||
|
||||
ret = read_acls(s, s->acl, s->bucket, obj_str);
|
||||
ret = read_acls(s, bucket_info, s->acl, s->bucket, obj_str);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -926,7 +921,7 @@ int RGWCopyObj::verify_permission()
|
||||
src_bucket = bucket_info.bucket;
|
||||
|
||||
/* just checking the bucket's permission */
|
||||
ret = read_acls(s, &src_policy, src_bucket, empty_str);
|
||||
ret = read_acls(s, bucket_info, &src_policy, src_bucket, empty_str);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -1008,7 +1003,7 @@ int RGWGetACLs::verify_permission()
|
||||
|
||||
void RGWGetACLs::execute()
|
||||
{
|
||||
ret = read_acls(s);
|
||||
ret = read_acls(s, false);
|
||||
|
||||
if (ret < 0) {
|
||||
send_response();
|
||||
|
@ -22,13 +22,6 @@ struct req_state;
|
||||
|
||||
/** Get the HTTP request metadata */
|
||||
extern void get_request_metadata(struct req_state *s, map<string, bufferlist>& attrs);
|
||||
/**
|
||||
* Get the ACL for an object off of disk. If you hold the req_state, use next
|
||||
* method.
|
||||
*/
|
||||
extern int read_acls(RGWAccessControlPolicy *policy, rgw_obj& bucket, string& object);
|
||||
/** Get the ACL needed for a request off of disk.*/
|
||||
extern int read_acls(struct req_state *s, bool only_bucket = false);
|
||||
|
||||
/**
|
||||
* Provide the base class for all ops.
|
||||
|
@ -939,56 +939,51 @@ int RGWRados::purge_buckets(std::string& id, vector<rgw_bucket>& buckets)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RGWRados::set_buckets_auid(vector<rgw_bucket>& buckets, uint64_t auid)
|
||||
int RGWRados::set_buckets_enabled(vector<rgw_bucket>& buckets, bool enabled)
|
||||
{
|
||||
librados::IoCtx ctx;
|
||||
vector<librados::PoolAsyncCompletion *> completions;
|
||||
int ret = 0;
|
||||
|
||||
vector<rgw_bucket>::iterator iter;
|
||||
|
||||
for (iter = buckets.begin(); iter != buckets.end(); ++iter) {
|
||||
rgw_bucket& bucket = *iter;
|
||||
int r = open_bucket_ctx(bucket, ctx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (enabled)
|
||||
dout(20) << "enabling bucket name=" << bucket.name << dendl;
|
||||
else
|
||||
dout(20) << "disabling bucket name=" << bucket.name << dendl;
|
||||
|
||||
librados::PoolAsyncCompletion *c = librados::Rados::pool_async_create_completion();
|
||||
completions.push_back(c);
|
||||
ctx.set_auid_async(auid, c);
|
||||
RGWBucketInfo info;
|
||||
int r = get_bucket_info(NULL, bucket.name, info);
|
||||
if (r < 0) {
|
||||
dout(0) << "get_bucket_info on bucket=" << bucket.name << " returned err=" << r << ", skipping bucket" << dendl;
|
||||
ret = r;
|
||||
continue;
|
||||
}
|
||||
if (enabled) {
|
||||
info.flags &= ~BUCKET_SUSPENDED;
|
||||
} else {
|
||||
info.flags |= BUCKET_SUSPENDED;
|
||||
}
|
||||
|
||||
r = put_bucket_info(bucket.name, info);
|
||||
if (r < 0) {
|
||||
dout(0) << "put_bucket_info on bucket=" << bucket.name << " returned err=" << r << ", skipping bucket" << dendl;
|
||||
ret = r;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
vector<librados::PoolAsyncCompletion *>::iterator citer;
|
||||
for (citer = completions.begin(); citer != completions.end(); ++citer) {
|
||||
PoolAsyncCompletion *c = *citer;
|
||||
c->wait();
|
||||
c->release();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RGWRados::disable_buckets(vector<rgw_bucket>& buckets)
|
||||
{
|
||||
return set_buckets_auid(buckets, RGW_SUSPENDED_USER_AUID);
|
||||
}
|
||||
|
||||
int RGWRados::enable_buckets(vector<rgw_bucket>& buckets, uint64_t auid)
|
||||
{
|
||||
return set_buckets_auid(buckets, auid);
|
||||
}
|
||||
|
||||
int RGWRados::bucket_suspended(rgw_bucket& bucket, bool *suspended)
|
||||
{
|
||||
librados::IoCtx ctx;
|
||||
int r = open_bucket_ctx(bucket, ctx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
uint64_t auid;
|
||||
int ret = ctx.get_auid(&auid);
|
||||
if (ret < 0)
|
||||
RGWBucketInfo bucket_info;
|
||||
int ret = rgwstore->get_bucket_info(NULL, bucket.name, bucket_info);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*suspended = (auid == RGW_SUSPENDED_USER_AUID);
|
||||
*suspended = ((bucket_info.flags & BUCKET_SUSPENDED) != 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1789,6 +1784,7 @@ int RGWRados::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime,
|
||||
mtime = ut.sec();
|
||||
} catch (buffer::error& err) {
|
||||
dout(0) << "ERROR: failed decoding object (obj=" << obj << ") info (either size or mtime), aborting" << dendl;
|
||||
return -EIO;
|
||||
}
|
||||
if (psize)
|
||||
*psize = size;
|
||||
@ -1848,6 +1844,18 @@ int RGWRados::get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& inf
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RGWRados::put_bucket_info(string& bucket_name, RGWBucketInfo& info)
|
||||
{
|
||||
bufferlist bl;
|
||||
|
||||
::encode(info, bl);
|
||||
|
||||
string unused;
|
||||
|
||||
int ret = rgw_put_obj(unused, pi_buckets_rados, bucket_name, bl.c_str(), bl.length());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RGWRados::tmap_get(rgw_obj& obj, bufferlist& header, std::map<string, bufferlist>& m)
|
||||
{
|
||||
|
@ -239,8 +239,7 @@ public:
|
||||
virtual int delete_bucket(std::string& id, rgw_bucket& bucket, bool remove_pool);
|
||||
virtual int purge_buckets(std::string& id, vector<rgw_bucket>& buckets);
|
||||
|
||||
virtual int disable_buckets(std::vector<rgw_bucket>& buckets);
|
||||
virtual int enable_buckets(std::vector<rgw_bucket>& buckets, uint64_t auid);
|
||||
virtual int set_buckets_enabled(std::vector<rgw_bucket>& buckets, bool enabled);
|
||||
virtual int bucket_suspended(rgw_bucket& bucket, bool *suspended);
|
||||
|
||||
/** Delete an object.*/
|
||||
@ -309,6 +308,7 @@ public:
|
||||
int decode_policy(bufferlist& bl, ACLOwner *owner);
|
||||
int get_bucket_stats(rgw_bucket& bucket, map<RGWObjCategory, RGWBucketStats>& stats);
|
||||
virtual int get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info);
|
||||
virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info);
|
||||
|
||||
int cls_rgw_init_index(rgw_bucket& bucket, string& oid);
|
||||
int cls_obj_prepare_op(rgw_bucket& bucket, uint8_t op, string& tag,
|
||||
|
Loading…
Reference in New Issue
Block a user