]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: support multiple host names 2563/head
authorYehuda Sadeh <yehuda@inktank.com>
Thu, 20 Feb 2014 02:00:10 +0000 (18:00 -0800)
committerYehuda Sadeh <yehuda@redhat.com>
Tue, 11 Nov 2014 21:27:32 +0000 (13:27 -0800)
Fixes: #7467
Allow configuration of multiple domain names. Still support a single
host name via the rgw_dns_name configurable but can add more names
through the region params.

Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
src/rgw/rgw_common.h
src/rgw/rgw_json_enc.cc
src/rgw/rgw_main.cc
src/rgw/rgw_rados.h
src/rgw/rgw_rest.cc
src/rgw/rgw_rest.h
src/rgw/rgw_rest_s3.cc

index 1170650b56aaef476decca088980b6b7c4bbfed2..c1d72347b19387fa958dd8ea68368c845835c5f7 100644 (file)
@@ -846,6 +846,7 @@ struct req_info {
   string request_uri;
   string effective_uri;
   string request_params;
+  string domain;
 
   req_info(CephContext *cct, RGWEnv *_env);
   void rebuild_from(req_info& src);
index 44db537c5ed727b9ded5d2e5fe432359c10533e7..4f5afb5545c29b8b991a13e09d0d7d9a6e46e224 100644 (file)
@@ -679,6 +679,7 @@ void RGWRegion::dump(Formatter *f) const
   encode_json("api_name", api_name, f);
   encode_json("is_master", is_master, f);
   encode_json("endpoints", endpoints, f);
+  encode_json("hostnames", hostnames, f);
   encode_json("master_zone", master_zone, f);
   encode_json_map("zones", zones, f); /* more friendly representation */
   encode_json_map("placement_targets", placement_targets, f); /* more friendly representation */
@@ -706,6 +707,7 @@ void RGWRegion::decode_json(JSONObj *obj)
   JSONDecoder::decode_json("api_name", api_name, obj);
   JSONDecoder::decode_json("is_master", is_master, obj);
   JSONDecoder::decode_json("endpoints", endpoints, obj);
+  JSONDecoder::decode_json("hostnames", hostnames, obj);
   JSONDecoder::decode_json("master_zone", master_zone, obj);
   JSONDecoder::decode_json("zones", zones, decode_zones, obj);
   JSONDecoder::decode_json("placement_targets", placement_targets, decode_placement_targets, obj);
index 2f2b755a762e2fb2d0a1a4fb54c917ca8a47103d..8ea12d8a54e0f7ccd5811a9f2217df25f9a4d69a 100644 (file)
@@ -1015,7 +1015,6 @@ int main(int argc, const char **argv)
   rgw_tools_init(g_ceph_context);
 
   rgw_init_resolver();
-  rgw_rest_init(g_ceph_context);
   
   curl_global_init(CURL_GLOBAL_ALL);
   
@@ -1030,6 +1029,8 @@ int main(int argc, const char **argv)
   if (!r)
     r = rgw_perf_start(g_ceph_context);
 
+  rgw_rest_init(g_ceph_context, store->region);
+
   mutex.Lock();
   init_timer.cancel_all_events();
   init_timer.shutdown();
index 99a87aac96b15e3fb7b5174a13f90c8c285003d3..6b71a610777c38e9e815c7bfcc12d22757be82da 100644 (file)
@@ -999,13 +999,15 @@ struct RGWRegion {
   map<string, RGWRegionPlacementTarget> placement_targets;
   string default_placement;
 
+  list<string> hostnames;
+
   CephContext *cct;
   RGWRados *store;
 
   RGWRegion() : is_master(false), cct(NULL), store(NULL) {}
 
   void encode(bufferlist& bl) const {
-    ENCODE_START(1, 1, bl);
+    ENCODE_START(2, 1, bl);
     ::encode(name, bl);
     ::encode(api_name, bl);
     ::encode(is_master, bl);
@@ -1014,11 +1016,12 @@ struct RGWRegion {
     ::encode(zones, bl);
     ::encode(placement_targets, bl);
     ::encode(default_placement, bl);
+    ::encode(hostnames, bl);
     ENCODE_FINISH(bl);
   }
 
   void decode(bufferlist::iterator& bl) {
-    DECODE_START(1, bl);
+    DECODE_START(2, bl);
     ::decode(name, bl);
     ::decode(api_name, bl);
     ::decode(is_master, bl);
@@ -1027,6 +1030,9 @@ struct RGWRegion {
     ::decode(zones, bl);
     ::decode(placement_targets, bl);
     ::decode(default_placement, bl);
+    if (struct_v >= 2) {
+      ::decode(hostnames, bl);
+    }
     DECODE_FINISH(bl);
   }
 
index 153628d5722c9faca19ea1f7fbc5356ef9da3057..117fe5b697cf9310badaf6eb1415a4170f868abb 100644 (file)
@@ -139,7 +139,9 @@ string camelcase_dash_http_attr(const string& orig)
   return string(buf);
 }
 
-void rgw_rest_init(CephContext *cct)
+static list<string> hostnames_list;
+
+void rgw_rest_init(CephContext *cct, RGWRegion& region)
 {
   for (struct rgw_http_attr *attr = rgw_to_http_attr_list; attr->rgw_attr; attr++) {
     rgw_to_http_attrs[attr->rgw_attr] = attr->http_attr;
@@ -168,6 +170,58 @@ void rgw_rest_init(CephContext *cct)
   for (const struct rgw_http_status_code *h = http_codes; h->code; h++) {
     http_status_names[h->code] = h->name;
   }
+
+  /* avoid duplicate hostnames in hostnames list */
+  map<string, bool> hostnames_map;
+  if (!cct->_conf->rgw_dns_name.empty()) {
+    hostnames_map[cct->_conf->rgw_dns_name] = true;
+  }
+  for (list<string>::iterator iter = region.hostnames.begin(); iter != region.hostnames.end(); ++iter) {
+    hostnames_map[*iter] = true;
+  }
+
+  for (map<string, bool>::iterator iter = hostnames_map.begin(); iter != hostnames_map.end(); ++iter) {
+    hostnames_list.push_back(iter->first);
+  }
+}
+
+static bool str_ends_with(const string& s, const string& suffix, size_t *pos)
+{
+  size_t len = suffix.size();
+  if (len > (size_t)s.size()) {
+    return false;
+  }
+
+  ssize_t p = s.size() - len;
+  if (pos) {
+    *pos = p;
+  }
+
+  return s.compare(p, len, suffix) == 0;
+}
+
+static bool rgw_find_host_in_domains(const string& host, string *domain, string *subdomain)
+{
+  list<string>::iterator iter;
+  for (iter = hostnames_list.begin(); iter != hostnames_list.end(); ++iter) {
+    size_t pos;
+    if (!str_ends_with(host, *iter, &pos))
+      continue;
+
+    *domain = host.substr(pos);
+    if (pos == 0) {
+      subdomain->clear();
+    } else {
+      if (host[pos - 1] != '.') {
+        continue;
+      }
+
+      *domain = host.substr(pos);
+      *subdomain = host.substr(0, pos - 1);
+    }
+    return true;
+  }
+  return false;
 }
 
 static void dump_status(struct req_state *s, const char *status, const char *status_name)
@@ -1194,34 +1248,45 @@ int RGWREST::preprocess(struct req_state *s, RGWClientIO *cio)
   req_info& info = s->info;
 
   s->cio = cio;
-  if (g_conf->rgw_dns_name.length() && info.host) {
+  if (info.host) {
     string h(s->info.host);
 
-    ldout(s->cct, 10) << "host=" << s->info.host << " rgw_dns_name=" << g_conf->rgw_dns_name << dendl;
-    int pos = h.find(g_conf->rgw_dns_name);
+    ldout(s->cct, 10) << "host=" << s->info.host << dendl;
+    string domain;
+    string subdomain;
+    bool in_hosted_domain = rgw_find_host_in_domains(h, &domain, &subdomain);
+    ldout(s->cct, 20) << "subdomain=" << subdomain << " domain=" << domain << " in_hosted_domain=" << in_hosted_domain << dendl;
 
-    if (g_conf->rgw_resolve_cname && pos < 0) {
+    if (g_conf->rgw_resolve_cname && !in_hosted_domain) {
       string cname;
       bool found;
       int r = rgw_resolver->resolve_cname(h, cname, &found);
       if (r < 0) {
-       dout(0) << "WARNING: rgw_resolver->resolve_cname() returned r=" << r << dendl;
+       ldout(s->cct, 0) << "WARNING: rgw_resolver->resolve_cname() returned r=" << r << dendl;
       }
       if (found) {
-        dout(0) << "resolved host cname " << h << " -> " << cname << dendl;
-       h = cname;
-        pos = h.find(g_conf->rgw_dns_name);
+        ldout(s->cct, 5) << "resolved host cname " << h << " -> " << cname << dendl;
+        in_hosted_domain = rgw_find_host_in_domains(cname, &domain, &subdomain);
+        ldout(s->cct, 20) << "subdomain=" << subdomain << " domain=" << domain << " in_hosted_domain=" << in_hosted_domain << dendl;
       }
     }
 
-    if (pos > 0 && h[pos - 1] == '.') {
+    if (in_hosted_domain && !subdomain.empty()) {
       string encoded_bucket = "/";
-      encoded_bucket.append(h.substr(0, pos-1));
+      encoded_bucket.append(subdomain);
       if (s->info.request_uri[0] != '/')
-       encoded_bucket.append("/'");
+        encoded_bucket.append("/'");
       encoded_bucket.append(s->info.request_uri);
       s->info.request_uri = encoded_bucket;
     }
+
+    if (!domain.empty()) {
+      s->info.domain = domain;
+    }
+  }
+
+  if (s->info.domain.empty()) {
+    s->info.domain = s->cct->_conf->rgw_dns_name;
   }
 
   url_decode(s->info.request_uri, s->decoded_uri);
index cc43c2ec49fbd0face55cf047559a7b68a49d695..430e3601e5e217401506cb1486488c22f2e9cc26 100644 (file)
@@ -13,7 +13,7 @@
 
 extern std::map<std::string, std::string> rgw_to_http_attrs;
 
-extern void rgw_rest_init(CephContext *cct);
+extern void rgw_rest_init(CephContext *cct, RGWRegion& region);
 
 extern void rgw_flush_formatter_and_reset(struct req_state *s,
                                         ceph::Formatter *formatter);
index 446a9e4732f0f39fe28fe3231a111362429d1a30..82efda60c788540460fb038921eb3a4f669b8e87 100644 (file)
@@ -1512,8 +1512,8 @@ void RGWCompleteMultipart_ObjStore_S3::send_response()
     dump_start(s);
     s->formatter->open_object_section_in_ns("CompleteMultipartUploadResult",
                          "http://s3.amazonaws.com/doc/2006-03-01/");
-    if (g_conf->rgw_dns_name.length())
-      s->formatter->dump_format("Location", "%s.%s", s->bucket_name_str.c_str(), g_conf->rgw_dns_name.c_str());
+    if (s->info.domain.length())
+      s->formatter->dump_format("Location", "%s.%s", s->bucket_name_str.c_str(), s->info.domain.c_str());
     s->formatter->dump_string("Bucket", s->bucket_name_str);
     s->formatter->dump_string("Key", s->object);
     s->formatter->dump_string("ETag", etag);