From: Yehuda Sadeh Date: Tue, 21 May 2013 21:07:21 +0000 (-0700) Subject: rgw: forward bucket creation to master region X-Git-Tag: v0.67-rc1~128^2~109 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=669e45eaaa8b7364c60666940a4e3f1df56dccf1;p=ceph.git rgw: forward bucket creation to master region plus many fixes. Signed-off-by: Yehuda Sadeh --- diff --git a/src/Makefile.am b/src/Makefile.am index ecde5c11320..befa68dda20 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2059,7 +2059,7 @@ noinst_HEADERS = \ rgw/rgw_cors_swift.h\ rgw/rgw_string.h\ rgw/rgw_formats.h\ - rgw/rgw_html_errors.h\ + rgw/rgw_http_errors.h\ rgw/rgw_log.h\ rgw/rgw_multi.h\ rgw/rgw_policy_s3.h\ diff --git a/src/rgw/rgw_html_errors.h b/src/rgw/rgw_html_errors.h deleted file mode 100644 index 16b06562956..00000000000 --- a/src/rgw/rgw_html_errors.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef RGW_HTML_ERRORS_H_ -#define RGW_HTML_ERRORS_H_ - -#include "rgw_common.h" - -struct rgw_html_errors { - int err_no; - int http_ret; - const char *s3_code; -}; - -const static struct rgw_html_errors RGW_HTML_ERRORS[] = { - { 0, 200, "" }, - { STATUS_CREATED, 201, "Created" }, - { STATUS_ACCEPTED, 202, "Accepted" }, - { STATUS_NO_CONTENT, 204, "NoContent" }, - { STATUS_PARTIAL_CONTENT, 206, "" }, - { ERR_PERMANENT_REDIRECT, 301, "PermanentRedirect" }, - { STATUS_REDIRECT, 303, "" }, - { ERR_NOT_MODIFIED, 304, "NotModified" }, - { EINVAL, 400, "InvalidArgument" }, - { ERR_INVALID_REQUEST, 400, "InvalidRequest" }, - { ERR_INVALID_DIGEST, 400, "InvalidDigest" }, - { ERR_BAD_DIGEST, 400, "BadDigest" }, - { ERR_INVALID_BUCKET_NAME, 400, "InvalidBucketName" }, - { ERR_INVALID_OBJECT_NAME, 400, "InvalidObjectName" }, - { ERR_UNRESOLVABLE_EMAIL, 400, "UnresolvableGrantByEmailAddress" }, - { ERR_INVALID_PART, 400, "InvalidPart" }, - { ERR_INVALID_PART_ORDER, 400, "InvalidPartOrder" }, - { ERR_REQUEST_TIMEOUT, 400, "RequestTimeout" }, - { ERR_TOO_LARGE, 400, "EntityTooLarge" }, - { ERR_TOO_SMALL, 400, "EntityTooSmall" }, - { ERR_TOO_MANY_BUCKETS, 400, "TooManyBuckets" }, - { ERR_LENGTH_REQUIRED, 411, "MissingContentLength" }, - { EACCES, 403, "AccessDenied" }, - { EPERM, 403, "AccessDenied" }, - { ERR_USER_SUSPENDED, 403, "UserSuspended" }, - { ERR_REQUEST_TIME_SKEWED, 403, "RequestTimeTooSkewed" }, - { ENOENT, 404, "NoSuchKey" }, - { ERR_NO_SUCH_BUCKET, 404, "NoSuchBucket" }, - { ERR_NO_SUCH_UPLOAD, 404, "NoSuchUpload" }, - { ERR_NOT_FOUND, 404, "Not Found"}, - { ERR_METHOD_NOT_ALLOWED, 405, "MethodNotAllowed" }, - { ETIMEDOUT, 408, "RequestTimeout" }, - { EEXIST, 409, "BucketAlreadyExists" }, - { ENOTEMPTY, 409, "BucketNotEmpty" }, - { ERR_PRECONDITION_FAILED, 412, "PreconditionFailed" }, - { ERANGE, 416, "InvalidRange" }, - { ERR_UNPROCESSABLE_ENTITY, 422, "UnprocessableEntity" }, - { ERR_INTERNAL_ERROR, 500, "InternalError" }, -}; - -const static struct rgw_html_errors RGW_HTML_SWIFT_ERRORS[] = { - { EACCES, 401, "AccessDenied" }, - { EPERM, 401, "AccessDenied" }, - { ERR_USER_SUSPENDED, 401, "UserSuspended" }, - { ERR_INVALID_UTF8, 412, "Invalid UTF8" }, - { ERR_BAD_URL, 412, "Bad URL" }, -}; - -#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0])) - -static inline const struct rgw_html_errors *search_err(int err_no, const struct rgw_html_errors *errs, int len) -{ - for (int i = 0; i < len; ++i, ++errs) { - if (err_no == errs->err_no) - return errs; - } - return NULL; -} - - - -#endif diff --git a/src/rgw/rgw_http_client.cc b/src/rgw/rgw_http_client.cc index 8472cfc750f..f51b5141afd 100644 --- a/src/rgw/rgw_http_client.cc +++ b/src/rgw/rgw_http_client.cc @@ -30,7 +30,7 @@ static size_t read_http_data(void *ptr, size_t size, size_t nmemb, void *_info) return len; } -int RGWHTTPClient::process(const string& url) +int RGWHTTPClient::process(const char *method, const char *url) { int ret = 0; CURL *curl_handle; @@ -52,7 +52,8 @@ int RGWHTTPClient::process(const string& url) h = curl_slist_append(h, val.c_str()); } - curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, method); + curl_easy_setopt(curl_handle, CURLOPT_URL, url); curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, read_http_header); diff --git a/src/rgw/rgw_http_client.h b/src/rgw/rgw_http_client.h index e11704fdf9e..5e8b55a61b6 100644 --- a/src/rgw/rgw_http_client.h +++ b/src/rgw/rgw_http_client.h @@ -18,7 +18,8 @@ public: virtual int read_header(void *ptr, size_t len) { return 0; } virtual int read_data(void *ptr, size_t len) { return 0; } - int process(const string& url); + int process(const char *method, const char *url); + int process(const char *url) { return process("GET", url); } }; #endif diff --git a/src/rgw/rgw_http_errors.h b/src/rgw/rgw_http_errors.h new file mode 100644 index 00000000000..1eb4e12e695 --- /dev/null +++ b/src/rgw/rgw_http_errors.h @@ -0,0 +1,94 @@ +#ifndef RGW_HTTP_ERRORS_H_ +#define RGW_HTTP_ERRORS_H_ + +#include "rgw_common.h" + +struct rgw_http_errors { + int err_no; + int http_ret; + const char *s3_code; +}; + +const static struct rgw_http_errors RGW_HTTP_ERRORS[] = { + { 0, 200, "" }, + { STATUS_CREATED, 201, "Created" }, + { STATUS_ACCEPTED, 202, "Accepted" }, + { STATUS_NO_CONTENT, 204, "NoContent" }, + { STATUS_PARTIAL_CONTENT, 206, "" }, + { ERR_PERMANENT_REDIRECT, 301, "PermanentRedirect" }, + { STATUS_REDIRECT, 303, "" }, + { ERR_NOT_MODIFIED, 304, "NotModified" }, + { EINVAL, 400, "InvalidArgument" }, + { ERR_INVALID_REQUEST, 400, "InvalidRequest" }, + { ERR_INVALID_DIGEST, 400, "InvalidDigest" }, + { ERR_BAD_DIGEST, 400, "BadDigest" }, + { ERR_INVALID_BUCKET_NAME, 400, "InvalidBucketName" }, + { ERR_INVALID_OBJECT_NAME, 400, "InvalidObjectName" }, + { ERR_UNRESOLVABLE_EMAIL, 400, "UnresolvableGrantByEmailAddress" }, + { ERR_INVALID_PART, 400, "InvalidPart" }, + { ERR_INVALID_PART_ORDER, 400, "InvalidPartOrder" }, + { ERR_REQUEST_TIMEOUT, 400, "RequestTimeout" }, + { ERR_TOO_LARGE, 400, "EntityTooLarge" }, + { ERR_TOO_SMALL, 400, "EntityTooSmall" }, + { ERR_TOO_MANY_BUCKETS, 400, "TooManyBuckets" }, + { ERR_LENGTH_REQUIRED, 411, "MissingContentLength" }, + { EACCES, 403, "AccessDenied" }, + { EPERM, 403, "AccessDenied" }, + { ERR_USER_SUSPENDED, 403, "UserSuspended" }, + { ERR_REQUEST_TIME_SKEWED, 403, "RequestTimeTooSkewed" }, + { ENOENT, 404, "NoSuchKey" }, + { ERR_NO_SUCH_BUCKET, 404, "NoSuchBucket" }, + { ERR_NO_SUCH_UPLOAD, 404, "NoSuchUpload" }, + { ERR_NOT_FOUND, 404, "Not Found"}, + { ERR_METHOD_NOT_ALLOWED, 405, "MethodNotAllowed" }, + { ETIMEDOUT, 408, "RequestTimeout" }, + { EEXIST, 409, "BucketAlreadyExists" }, + { ENOTEMPTY, 409, "BucketNotEmpty" }, + { ERR_PRECONDITION_FAILED, 412, "PreconditionFailed" }, + { ERANGE, 416, "InvalidRange" }, + { ERR_UNPROCESSABLE_ENTITY, 422, "UnprocessableEntity" }, + { ERR_INTERNAL_ERROR, 500, "InternalError" }, +}; + +const static struct rgw_http_errors RGW_HTTP_SWIFT_ERRORS[] = { + { EACCES, 401, "AccessDenied" }, + { EPERM, 401, "AccessDenied" }, + { ERR_USER_SUSPENDED, 401, "UserSuspended" }, + { ERR_INVALID_UTF8, 412, "Invalid UTF8" }, + { ERR_BAD_URL, 412, "Bad URL" }, +}; + +#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0])) + +static inline const struct rgw_http_errors *search_err(int err_no, const struct rgw_http_errors *errs, int len) +{ + for (int i = 0; i < len; ++i, ++errs) { + if (err_no == errs->err_no) + return errs; + } + return NULL; +} + + +static inline int rgw_http_error_to_errno(int http_err) +{ + if (http_err >= 200 && http_err <= 299) + return 0; + switch (http_err) { + case 400: + return -EINVAL; + case 401: + return -EPERM; + case 403: + return -EACCES; + case 404: + return -ENOENT; + default: + return -EIO; + } + + return 0; /* unreachable */ +} + + +#endif diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index d3b3e03c300..7a870236890 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -860,10 +860,15 @@ void RGWCreateBucket::execute() if (!store->region.is_master) { if (store->region.api_name != location_constraint) { - ldout(s->cct, 0) << "location constraint (" << location_constraint << ") doesn't match region" << dendl; + ldout(s->cct, 0) << "location constraint (" << location_constraint << ") doesn't match region" << " (" << store->region.api_name << ")" << dendl; ret = -EINVAL; return; } + + ldout(s->cct, 0) << "sending create_bucket request to master region" << dendl; + ret = store->rest_conn->create_bucket(s->user.user_id, s->bucket_name_str); + if (ret < 0) + return; } s->bucket_owner.set_id(s->user.user_id); diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 15408818825..30ce936aa90 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -504,6 +504,7 @@ void RGWRados::finalize() delete gc; gc = NULL; } + delete rest_conn; } /** @@ -553,6 +554,10 @@ int RGWRados::init_complete() ldout(cct, 0) << "WARNING: cannot read region map" << dendl; } else { string master_region = region_map.master_region; + if (master_region.empty()) { + lderr(cct) << "ERROR: region map does not specify master region" << dendl; + return -EINVAL; + } map::iterator iter = region_map.regions.find(master_region); if (iter == region_map.regions.end()) { lderr(cct) << "ERROR: bad region map: inconsistent master region" << dendl; diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc index b7c8e69ea0c..9f093bac1d2 100644 --- a/src/rgw/rgw_rest.cc +++ b/src/rgw/rgw_rest.cc @@ -189,20 +189,20 @@ void rgw_flush_formatter(struct req_state *s, Formatter *formatter) void set_req_state_err(struct req_state *s, int err_no) { - const struct rgw_html_errors *r; + const struct rgw_http_errors *r; if (err_no < 0) err_no = -err_no; s->err.ret = err_no; if (s->prot_flags & RGW_REST_SWIFT) { - r = search_err(err_no, RGW_HTML_SWIFT_ERRORS, ARRAY_LEN(RGW_HTML_SWIFT_ERRORS)); + r = search_err(err_no, RGW_HTTP_SWIFT_ERRORS, ARRAY_LEN(RGW_HTTP_SWIFT_ERRORS)); if (r) { s->err.http_ret = r->http_ret; s->err.s3_code = r->s3_code; return; } } - r = search_err(err_no, RGW_HTML_ERRORS, ARRAY_LEN(RGW_HTML_ERRORS)); + r = search_err(err_no, RGW_HTTP_ERRORS, ARRAY_LEN(RGW_HTTP_ERRORS)); if (r) { s->err.http_ret = r->http_ret; s->err.s3_code = r->s3_code; diff --git a/src/rgw/rgw_rest_client.cc b/src/rgw/rgw_rest_client.cc index 0d896652277..d3caaa5c849 100644 --- a/src/rgw/rgw_rest_client.cc +++ b/src/rgw/rgw_rest_client.cc @@ -1,5 +1,6 @@ #include "rgw_common.h" #include "rgw_rest_client.h" +#include "rgw_http_errors.h" #include "common/ceph_crypto_cms.h" #include "common/armor.h" @@ -21,15 +22,15 @@ int RGWRESTClient::read_header(void *ptr, size_t len) } if (*s == '\n') { *p = '\0'; - ldout(cct, 10) << "os_auth:" << line << dendl; + ldout(cct, 10) << "received header:" << line << dendl; // TODO: fill whatever data required here char *l = line; char *tok = strsep(&l, " \t:"); - if (tok) { - while (l && *l == ' ') + if (tok && l) { + while (*l == ' ') l++; - if (strcmp(tok, "HTTP") == 0) { + if (strcmp(tok, "HTTP") == 0 || strncmp(tok, "HTTP/", 5) == 0) { status = atoi(l); } else { /* convert header field name to upper case */ @@ -50,7 +51,7 @@ int RGWRESTClient::read_header(void *ptr, size_t len) return 0; } -int RGWRESTClient::execute(RGWAccessKey& key, const string& method, const string& resource) +int RGWRESTClient::execute(RGWAccessKey& key, const char *method, const char *resource) { string new_url = url; string new_resource = resource; @@ -68,6 +69,8 @@ int RGWRESTClient::execute(RGWAccessKey& key, const string& method, const string list >::iterator iter; for (iter = params.begin(); iter != params.end(); ++iter) { + if (iter != params.begin()) + new_url.append("?"); new_url.append(iter->first + "=" + iter->second); } } @@ -78,7 +81,7 @@ int RGWRESTClient::execute(RGWAccessKey& key, const string& method, const string string date_str = s.str(); headers.push_back(make_pair("HTTP_DATE", date_str)); - string canonical_header = method + " " + + string canonical_header = string(method) + " " + "\n" + /* CONTENT_MD5 */ "\n" + /* CONTENT_TYPE */ date_str + "\n" + @@ -103,7 +106,11 @@ int RGWRESTClient::execute(RGWAccessKey& key, const string& method, const string string auth_hdr = "AWS " + key.id + ":" + b64; headers.push_back(make_pair("AUTHORIZATION", auth_hdr)); - return process(new_url); + int r = process(method, new_url.c_str()); + if (r < 0) + return r; + + return rgw_http_error_to_errno(status); } diff --git a/src/rgw/rgw_rest_client.h b/src/rgw/rgw_rest_client.h index f885a223d84..95e1f28697d 100644 --- a/src/rgw/rgw_rest_client.h +++ b/src/rgw/rgw_rest_client.h @@ -15,11 +15,9 @@ protected: map out_headers; list > params; - - RGWRESTClient() : cct(NULL), status(0) {} public: - RGWRESTClient(CephContext *_cct, string& _url, - list > *_headers, list > *_params) : cct(_cct), url(_url) { + RGWRESTClient(CephContext *_cct, string& _url, list > *_headers, + list > *_params) : cct(_cct), status(0), url(_url) { if (_headers) headers = *_headers; @@ -29,7 +27,7 @@ public: int read_header(void *ptr, size_t len); - int execute(RGWAccessKey& key, const string& method, const string& resource); + int execute(RGWAccessKey& key, const char *method, const char *resource); }; diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 6af11b036c2..a9010d64763 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -39,10 +39,10 @@ void dump_bucket(struct req_state *s, RGWBucketEnt& obj) s->formatter->close_section(); } -void rgw_get_errno_s3(rgw_html_errors *e , int err_no) +void rgw_get_errno_s3(rgw_http_errors *e , int err_no) { - const struct rgw_html_errors *r; - r = search_err(err_no, RGW_HTML_ERRORS, ARRAY_LEN(RGW_HTML_ERRORS)); + const struct rgw_http_errors *r; + r = search_err(err_no, RGW_HTTP_ERRORS, ARRAY_LEN(RGW_HTTP_ERRORS)); if (r) { e->http_ret = r->http_ret; @@ -1593,7 +1593,7 @@ void RGWDeleteMultiObj_ObjStore_S3::send_partial_response(pair& resu s->formatter->dump_string("Key", result.first); s->formatter->close_section(); } else if (result.first < 0) { - struct rgw_html_errors r; + struct rgw_http_errors r; int err_no; s->formatter->open_object_section("Error"); diff --git a/src/rgw/rgw_rest_s3.h b/src/rgw/rgw_rest_s3.h index ea8e5edc2cb..d2f9d7f4baf 100644 --- a/src/rgw/rgw_rest_s3.h +++ b/src/rgw/rgw_rest_s3.h @@ -3,13 +3,13 @@ #define TIME_BUF_SIZE 128 #include "rgw_op.h" -#include "rgw_html_errors.h" +#include "rgw_http_errors.h" #include "rgw_acl_s3.h" #include "rgw_policy_s3.h" #define RGW_AUTH_GRACE_MINS 15 -void rgw_get_errno_s3(struct rgw_html_errors *e, int err_no); +void rgw_get_errno_s3(struct rgw_http_errors *e, int err_no); class RGWGetObj_ObjStore_S3 : public RGWGetObj_ObjStore { diff --git a/src/rgw/rgw_swift.cc b/src/rgw/rgw_swift.cc index 9b9b1bbefb1..56933b3d722 100644 --- a/src/rgw/rgw_swift.cc +++ b/src/rgw/rgw_swift.cc @@ -396,7 +396,7 @@ int RGWSwift::check_revoked() req.append_header("X-Auth-Token", g_conf->rgw_keystone_admin_token); - int ret = req.process(url); + int ret = req.process(url.c_str()); if (ret < 0) return ret; @@ -604,7 +604,7 @@ int RGWSwift::validate_keystone_token(RGWRados *store, const string& token, stru validate.append_header("X-Auth-Token", g_conf->rgw_keystone_admin_token); - int ret = validate.process(url); + int ret = validate.process(url.c_str()); if (ret < 0) return ret; }