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