]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: forward bucket creation to master region
authorYehuda Sadeh <yehuda@inktank.com>
Tue, 21 May 2013 21:07:21 +0000 (14:07 -0700)
committerYehuda Sadeh <yehuda@inktank.com>
Tue, 21 May 2013 21:07:21 +0000 (14:07 -0700)
plus many fixes.

Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
13 files changed:
src/Makefile.am
src/rgw/rgw_html_errors.h [deleted file]
src/rgw/rgw_http_client.cc
src/rgw/rgw_http_client.h
src/rgw/rgw_http_errors.h [new file with mode: 0644]
src/rgw/rgw_op.cc
src/rgw/rgw_rados.cc
src/rgw/rgw_rest.cc
src/rgw/rgw_rest_client.cc
src/rgw/rgw_rest_client.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_s3.h
src/rgw/rgw_swift.cc

index ecde5c1132090191f05a3b6b54252c92dac20066..befa68dda207c222e2db385bc4dcb2a8955e38d2 100644 (file)
@@ -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 (file)
index 16b0656..0000000
+++ /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
index 8472cfc750f92f8e12823c3e40bbea38404e483d..f51b5141afdfce82fcc587097e01bed1b6d25aa7 100644 (file)
@@ -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);
index e11704fdf9e67a52063222ba25eb0ed0bb7e7c2e..5e8b55a61b63891666af7ded1ceaa928b6e5e04a 100644 (file)
@@ -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 (file)
index 0000000..1eb4e12
--- /dev/null
@@ -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
index d3b3e03c300d8030c7a8a258ce219768a758988e..7a870236890c4fc7770078947aec38d300706a3b 100644 (file)
@@ -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);
index 154088188257a5bc1066484800e996602dd8862b..30ce936aa904b9b3d331afa71ab7ce0c17d2e9fa 100644 (file)
@@ -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<string, RGWRegion>::iterator iter = region_map.regions.find(master_region);
     if (iter == region_map.regions.end()) {
       lderr(cct) << "ERROR: bad region map: inconsistent master region" << dendl;
index b7c8e69ea0caec851594b142726559df63ae6482..9f093bac1d22357491427f0cf5e12e789b6b8638 100644 (file)
@@ -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;
index 0d8966522779185988b7e7d7df0ce65617363b8e..d3caaa5c849648140fbfbfc615ad6dcb6f74a06d 100644 (file)
@@ -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<pair<string, string> >::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<string, string>("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<string, string>("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);
 }
 
 
index f885a223d8482650d0b48913c9e8daa870fa5173..95e1f28697df54838ba3258688852b0f2b47793f 100644 (file)
@@ -15,11 +15,9 @@ protected:
 
   map<string, string> out_headers;
   list<pair<string, string> > params;
-
-  RGWRESTClient() : cct(NULL), status(0) {}
 public:
-  RGWRESTClient(CephContext *_cct, string& _url,
-                list<pair<string, string> > *_headers, list<pair<string, string> > *_params) : cct(_cct), url(_url) {
+  RGWRESTClient(CephContext *_cct, string& _url, list<pair<string, string> > *_headers,
+                list<pair<string, string> > *_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);
 };
 
 
index 6af11b036c27a66b57a20ded31ba64b42e1225cd..a9010d647637a996e92279a16c2bc1019c418101 100644 (file)
@@ -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<string,int>& 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");
index ea8e5edc2cbb05f3886a00909bb2c564f6401251..d2f9d7f4baf701724530f646dd7b1dbae5d54d05 100644 (file)
@@ -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
 {
index 9b9b1bbefb1d22cf07671a5a9bfc5b3c57c8840d..56933b3d7222239c1c98b40bb4a3d33d8ad5764d 100644 (file)
@@ -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;
   }