RGW_OBJ_CATEGORY_MULTIMETA = 3,
};
+enum HostStyle {
+ PathStyle = 0,
+ VirtualStyle = 1,
+};
+
/** Store error returns for output at a different point in the program */
struct rgw_err {
rgw_err();
void RGWRESTStreamS3PutObj::send_init(rgw_obj& obj)
{
+ string resource_str;
string resource;
- url_encode(obj.bucket.name + "/" + obj.get_oid(), resource);
string new_url = url;
+
+ if (host_style == VirtualStyle) {
+ resource_str = obj.get_oid();
+ new_url = obj.bucket.name + "." + new_url;
+ } else {
+ resource_str = obj.bucket.name + "/" + obj.get_oid();
+ }
+
+ //do not encode slash in object key name
+ url_encode(resource_str, resource, false);
+
+ string uri;
+ //do not encode slash in object key name
+ url_encode(obj.bucket.name + "/" + obj.get_oid(), uri, false);
+
if (new_url[new_url.size() - 1] != '/')
new_url.append("/");
new_info.method = "PUT";
new_info.script_uri = "/";
- new_info.script_uri.append(resource);
+ new_info.script_uri.append(uri);
new_info.request_uri = new_info.script_uri;
method = new_info.method;
string new_url = url;
if (new_url[new_url.size() - 1] != '/')
new_url.append("/");
-
+
string date_str;
get_gmt_date_str(date_str);
}
string new_resource;
+ string bucket_name;
+ string old_resource = resource;
+
if (resource[0] == '/') {
new_resource = resource.substr(1);
} else {
new_resource = resource;
}
+ string uri = new_resource;
+
+ size_t pos = new_resource.find("/");
+ bucket_name = new_resource.substr(0, pos);
+
+ //when dest is a bucket with out other params, uri should end up with '/'
+ if(pos == string::npos && params.size() == 0 && host_style == VirtualStyle) {
+ uri.append("/");
+ }
+
+ if (host_style == VirtualStyle) {
+ new_url = bucket_name + "." + new_url;
+ if(pos == string::npos) {
+ new_resource = "";
+ } else {
+ new_resource = new_resource.substr(pos+1);
+ }
+ }
+
new_url.append(new_resource + params_str);
new_env.set("HTTP_DATE", date_str.c_str());
new_info.method = method.c_str();
new_info.script_uri = "/";
- new_info.script_uri.append(new_resource);
+ new_info.script_uri.append(uri);
new_info.request_uri = new_info.script_uri;
new_info.init_meta_info(NULL);
class RGWRESTStreamRWRequest : public RGWHTTPStreamRWRequest {
bool send_data_hint{false};
+protected:
+ HostStyle host_style;
public:
RGWRESTStreamRWRequest(CephContext *_cct, const string& _method, const string& _url, RGWHTTPStreamRWRequest::ReceiveCB *_cb,
- param_vec_t *_headers, param_vec_t *_params) : RGWHTTPStreamRWRequest(_cct, _method, _url, _cb, _headers, _params) {
+ param_vec_t *_headers, param_vec_t *_params, HostStyle _host_style = PathStyle) : RGWHTTPStreamRWRequest(_cct, _method, _url, _cb, _headers, _params), host_style(_host_style) {
}
virtual ~RGWRESTStreamRWRequest() override {}
class RGWRESTStreamReadRequest : public RGWRESTStreamRWRequest {
public:
RGWRESTStreamReadRequest(CephContext *_cct, const string& _url, ReceiveCB *_cb, param_vec_t *_headers,
- param_vec_t *_params) : RGWRESTStreamRWRequest(_cct, "GET", _url, _cb, _headers, _params) {}
+ param_vec_t *_params, HostStyle _host_style = PathStyle) : RGWRESTStreamRWRequest(_cct, "GET", _url, _cb, _headers, _params, _host_style) {}
};
class RGWRESTStreamHeadRequest : public RGWRESTStreamRWRequest {
req_info new_info;
public:
RGWRESTStreamS3PutObj(CephContext *_cct, const string& _method, const string& _url, param_vec_t *_headers,
- param_vec_t *_params) : RGWRESTStreamRWRequest(_cct, _method, _url, nullptr, _headers, _params),
+ param_vec_t *_params, HostStyle _host_style) : RGWRESTStreamRWRequest(_cct, _method, _url, nullptr, _headers, _params, _host_style),
out_cb(NULL), new_info(cct, &new_env) {}
~RGWRESTStreamS3PutObj() override;
RGWRESTConn::RGWRESTConn(CephContext *_cct, RGWRados *store,
const string& _remote_id,
- const list<string>& remote_endpoints)
+ const list<string>& remote_endpoints,
+ HostStyle _host_style)
: cct(_cct),
endpoints(remote_endpoints.begin(), remote_endpoints.end()),
- remote_id(_remote_id)
+ remote_id(_remote_id), host_style(_host_style)
{
if (store) {
key = store->get_zone_params().system_key;
RGWRESTConn::RGWRESTConn(CephContext *_cct, RGWRados *store,
const string& _remote_id,
const list<string>& remote_endpoints,
- RGWAccessKey _cred)
+ RGWAccessKey _cred,
+ HostStyle _host_style)
: cct(_cct),
endpoints(remote_endpoints.begin(), remote_endpoints.end()),
key(std::move(_cred)),
- remote_id(_remote_id)
+ remote_id(_remote_id), host_style(_host_style)
{
if (store) {
self_zone_group = store->get_zonegroup().get_id();
append_param_list(params, extra_params);
}
- RGWRESTStreamS3PutObj *wr = new RGWRESTStreamS3PutObj(cct, "PUT", url, NULL, ¶ms);
+ RGWRESTStreamS3PutObj *wr = new RGWRESTStreamS3PutObj(cct, "PUT", url, NULL, ¶ms, host_style);
wr->send_init(obj);
*req = wr;
return 0;
param_vec_t params;
populate_params(params, &uid, self_zone_group);
- RGWRESTStreamS3PutObj *wr = new RGWRESTStreamS3PutObj(cct, "PUT", url, NULL, ¶ms);
+ RGWRESTStreamS3PutObj *wr = new RGWRESTStreamS3PutObj(cct, "PUT", url, NULL, ¶ms, host_style);
ret = wr->put_obj_init(key, obj, obj_size, attrs, send);
if (ret < 0) {
delete wr;
params.push_back(param_pair_t("versionId", instance));
}
if (in_params.get_op) {
- *req = new RGWRESTStreamReadRequest(cct, url, in_params.cb, NULL, ¶ms);
+ *req = new RGWRESTStreamReadRequest(cct, url, in_params.cb, NULL, ¶ms, host_style);
} else {
*req = new RGWRESTStreamHeadRequest(cct, url, in_params.cb, NULL, ¶ms);
}
RGWStreamIntoBufferlist cb(bl);
- RGWRESTStreamReadRequest req(cct, url, &cb, NULL, ¶ms);
+ RGWRESTStreamReadRequest req(cct, url, &cb, NULL, ¶ms, host_style);
map<string, string> headers;
if (extra_headers) {
RGWHTTPManager *_mgr)
: cct(_conn->get_ctx()), conn(_conn), method(_method), resource(_resource),
params(make_param_list(pp)), cb(bl), mgr(_mgr),
- req(cct, method.c_str(), conn->get_url(), &cb, NULL, NULL)
+ req(cct, method.c_str(), conn->get_url(), &cb, NULL, NULL, _conn->get_host_style())
{
init_common(extra_headers);
}
param_vec_t *extra_headers,
RGWHTTPManager *_mgr)
: cct(_conn->get_ctx()), conn(_conn), method(_method), resource(_resource), params(params),
- cb(bl), mgr(_mgr), req(cct, method.c_str(), conn->get_url(), &cb, NULL, NULL)
+ cb(bl), mgr(_mgr), req(cct, method.c_str(), conn->get_url(), &cb, NULL, NULL, _conn->get_host_style())
{
init_common(extra_headers);
}
RGWAccessKey key;
string self_zone_group;
string remote_id;
+ HostStyle host_style;
std::atomic<int64_t> counter = { 0 };
public:
- RGWRESTConn(CephContext *_cct, RGWRados *store, const string& _remote_id, const list<string>& endpoints);
- RGWRESTConn(CephContext *_cct, RGWRados *store, const string& _remote_id, const list<string>& endpoints, RGWAccessKey _cred);
+ RGWRESTConn(CephContext *_cct, RGWRados *store, const string& _remote_id, const list<string>& endpoints, HostStyle _host_style = PathStyle);
+ RGWRESTConn(CephContext *_cct, RGWRados *store, const string& _remote_id, const list<string>& endpoints, RGWAccessKey _cred, HostStyle _host_style = PathStyle);
+
// custom move needed for atomic
RGWRESTConn(RGWRESTConn&& other);
RGWRESTConn& operator=(RGWRESTConn&& other);
return key;
}
+ HostStyle get_host_style() {
+ return host_style;
+ }
+
CephContext *get_ctx() {
return cct;
}
public:
- S3RESTConn(CephContext *_cct, RGWRados *store, const string& _remote_id, const list<string>& endpoints) :
- RGWRESTConn(_cct, store, _remote_id, endpoints) {}
+ S3RESTConn(CephContext *_cct, RGWRados *store, const string& _remote_id, const list<string>& endpoints, HostStyle _host_style = PathStyle) :
+ RGWRESTConn(_cct, store, _remote_id, endpoints, _host_style) {}
- S3RESTConn(CephContext *_cct, RGWRados *store, const string& _remote_id, const list<string>& endpoints, RGWAccessKey _cred):
- RGWRESTConn(_cct, store, _remote_id, endpoints, _cred) {}
+ S3RESTConn(CephContext *_cct, RGWRados *store, const string& _remote_id, const list<string>& endpoints, RGWAccessKey _cred, HostStyle _host_style = PathStyle):
+ RGWRESTConn(_cct, store, _remote_id, endpoints, _cred, _host_style) {}
~S3RESTConn() override = default;
void populate_params(param_vec_t& params, const rgw_user *uid, const string& zonegroup) override {
}
static string aws_object_name(const RGWBucketInfo& bucket_info, const rgw_obj_key&key, bool user_buckets=false){
- string bucket_name = aws_bucket_name(bucket_info, user_buckets);
string object_name;
object_name += bucket_info.owner.to_str() + "/";
object_name += bucket_info.bucket.name + "/" + key.name;
struct AWSSyncConfig {
string s3_endpoint;
RGWAccessKey key;
+ HostStyle host_style;
+
uint64_t multipart_sync_threshold{DEFAULT_MULTIPART_SYNC_PART_SIZE};
uint64_t multipart_min_part_size{DEFAULT_MULTIPART_SYNC_PART_SIZE};
unordered_map <string, bool> bucket_created;
string target_bucket_name;
rgw_rest_obj rest_obj;
- string obj_path;
int ret{0};
uint32_t src_zone_short_id{0};
return set_cr_error(-EINVAL);
}
- obj_path = bucket_info.bucket.name + "/" + key.name;
-
target_bucket_name = aws_bucket_name(bucket_info);
if (bucket_created.find(target_bucket_name) == bucket_created.end()){
yield {
sync_env->store,
instance.id,
{ instance.conf.s3_endpoint },
- instance.conf.key));
+ instance.conf.key,
+ instance.conf.host_style));
}
~RGWAWSDataSyncModule() {}
conf.s3_endpoint = config["s3_endpoint"];
+ i = config.find("host_style");
+ string host_style_str = config["host_style"];
+
+ if (host_style_str != "virtual") {
+ conf.host_style = PathStyle;
+ } else {
+ conf.host_style = VirtualStyle;
+ }
+
+ conf.bucket_suffix = config["bucket_suffix"];
+
string access_key = config["access_key"];
string secret = config["secret"];