#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
-#include "include/assert.h"
+#include "include/ceph_assert.h"
#include "ceph_ver.h"
#include "common/Formatter.h"
#include "rgw_request.h"
#include "rgw_process.h"
+#include "rgw_zone.h"
+
+#include "services/svc_zone.h"
+
#include <array>
#include <sstream>
#include <memory>
static void dump_account_metadata(struct req_state * const s,
const RGWUsageStats& global_stats,
- const std::map<std::string, RGWUsageStats> policies_stats,
+ const std::map<std::string, RGWUsageStats> &policies_stats,
/* const */map<string, bufferlist>& attrs,
const RGWQuotaInfo& quota,
const RGWAccessControlPolicy_SWIFTAcct &policy)
user_quota,
static_cast<RGWAccessControlPolicy_SWIFTAcct&>(*s->user_acl));
dump_errno(s);
+ dump_header(s, "Accept-Ranges", "bytes");
end_header(s, NULL, NULL, NO_CONTENT_LENGTH, true);
}
if (write_acl.size()) {
dump_header(s, "X-Container-Write", write_acl);
}
- if (!s->bucket_info.placement_rule.empty()) {
- dump_header(s, "X-Storage-Policy", s->bucket_info.placement_rule);
+ if (!s->bucket_info.placement_rule.name.empty()) {
+ dump_header(s, "X-Storage-Policy", s->bucket_info.placement_rule.name);
}
+ dump_header(s, "X-Storage-Class", s->bucket_info.placement_rule.get_storage_class());
/* Dump user-defined metadata items and generic attrs. */
const size_t PREFIX_LEN = sizeof(RGW_ATTR_META_PREFIX) - 1;
if (ws_conf.listing_enabled) {
dump_header(s, "X-Container-Meta-Web-Listings", "true");
}
+
+ /* Dump bucket's modification time. Compliance with the Swift API really
+ * needs that. */
+ dump_last_modified(s, s->bucket_mtime);
}
void RGWStatAccount_ObjStore_SWIFT::execute()
policy.create_default(s->user->user_id, s->user->display_name);
}
- location_constraint = store->get_zonegroup().api_name;
+ location_constraint = store->svc.zone->get_zonegroup().api_name;
get_rmattrs_from_headers(s, CONT_PUT_ATTR_PREFIX,
CONT_REMOVE_ATTR_PREFIX, rmattr_names);
- placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");
+ placement_rule.init(s->info.env->get("HTTP_X_STORAGE_POLICY", ""), s->info.storage_class);
return get_swift_versioning_settings(s, swift_ver_location);
}
* (stored as xattr) size. */
const auto error_message = boost::str(
boost::format("Metadata value longer than %lld")
- % s->cct->_conf->get_val<size_t>("rgw_max_attr_size"));
+ % s->cct->_conf.get_val<Option::size_t>("rgw_max_attr_size"));
set_req_state_err(s, EINVAL, error_message);
return -EINVAL;
} else if (op_ret == -E2BIG) {
const auto error_message = boost::str(
boost::format("Too many metadata items; max %lld")
- % s->cct->_conf->get_val<size_t>("rgw_max_attrs_num_in_req"));
+ % s->cct->_conf.get_val<uint64_t>("rgw_max_attrs_num_in_req"));
set_req_state_err(s, EINVAL, error_message);
return -EINVAL;
}
}
}
+int RGWPutObj_ObjStore_SWIFT::update_slo_segment_size(rgw_slo_entry& entry) {
+
+ int r = 0;
+ const string& path = entry.path;
+
+ /* If the path starts with slashes, strip them all. */
+ const size_t pos_init = path.find_first_not_of('/');
+
+ if (pos_init == string::npos) {
+ return -EINVAL;
+ }
+
+ const size_t pos_sep = path.find('/', pos_init);
+ if (pos_sep == string::npos) {
+ return -EINVAL;
+ }
+
+ string bucket_name = path.substr(pos_init, pos_sep - pos_init);
+ string obj_name = path.substr(pos_sep + 1);
+
+ rgw_bucket bucket;
+
+ if (bucket_name.compare(s->bucket.name) != 0) {
+ RGWBucketInfo bucket_info;
+ map<string, bufferlist> bucket_attrs;
+ auto obj_ctx = store->svc.sysobj->init_obj_ctx();
+ r = store->get_bucket_info(obj_ctx, s->user->user_id.tenant,
+ bucket_name, bucket_info, nullptr,
+ &bucket_attrs);
+ if (r < 0) {
+ ldpp_dout(this, 0) << "could not get bucket info for bucket="
+ << bucket_name << dendl;
+ return r;
+ }
+ bucket = bucket_info.bucket;
+ } else {
+ bucket = s->bucket;
+ }
+
+ /* fetch the stored size of the seg (or error if not valid) */
+ rgw_obj_key slo_key(obj_name);
+ rgw_obj slo_seg(bucket, slo_key);
+
+ /* no prefetch */
+ RGWObjectCtx obj_ctx(store);
+ obj_ctx.set_atomic(slo_seg);
+
+ RGWRados::Object op_target(store, s->bucket_info, obj_ctx, slo_seg);
+ RGWRados::Object::Read read_op(&op_target);
+
+ bool compressed;
+ RGWCompressionInfo cs_info;
+ map<std::string, buffer::list> attrs;
+ uint64_t size_bytes{0};
+
+ read_op.params.attrs = &attrs;
+ read_op.params.obj_size = &size_bytes;
+
+ r = read_op.prepare();
+ if (r < 0) {
+ return r;
+ }
+
+ r = rgw_compression_info_from_attrset(attrs, compressed, cs_info);
+ if (r < 0) {
+ return -EIO;
+ }
+
+ if (compressed) {
+ size_bytes = cs_info.orig_size;
+ }
+
+ /* "When the PUT operation sees the multipart-manifest=put query
+ * parameter, it reads the request body and verifies that each
+ * segment object exists and that the sizes and ETags match. If
+ * there is a mismatch, the PUT operation fails."
+ */
+ if (entry.size_bytes &&
+ (entry.size_bytes != size_bytes)) {
+ return -EINVAL;
+ }
+
+ entry.size_bytes = size_bytes;
+
+ return 0;
+} /* RGWPutObj_ObjStore_SWIFT::update_slo_segment_sizes */
+
int RGWPutObj_ObjStore_SWIFT::get_params()
{
if (s->has_bad_meta) {
slo_info = new RGWSLOInfo;
- int r = rgw_rest_get_json_input_keep_data(s->cct, s, slo_info->entries, max_len, &slo_info->raw_data, &slo_info->raw_data_len);
+ int r = 0;
+ std::tie(r, slo_info->raw_data) = rgw_rest_get_json_input_keep_data(s->cct, s, slo_info->entries, max_len);
if (r < 0) {
ldout(s->cct, 5) << "failed to read input for slo r=" << r << dendl;
return r;
MD5 etag_sum;
uint64_t total_size = 0;
- for (const auto& entry : slo_info->entries) {
- etag_sum.Update((const byte *)entry.etag.c_str(),
+ for (auto& entry : slo_info->entries) {
+ etag_sum.Update((const unsigned char *)entry.etag.c_str(),
entry.etag.length());
+
+ /* if size_bytes == 0, it should be replaced with the
+ * real segment size (which could be 0); this follows from the
+ * fact that Swift requires all segments to exist, but permits
+ * the size_bytes element to be omitted from the SLO manifest, see
+ * https://docs.openstack.org/swift/latest/api/large_objects.html
+ */
+ r = update_slo_segment_size(entry);
+ if (r < 0) {
+ return r;
+ }
+
total_size += entry.size_bytes;
ldout(s->cct, 20) << "slo_part: " << entry.path
complete_etag(etag_sum, &lo_etag);
slo_info->total_size = total_size;
- ofs = slo_info->raw_data_len;
+ ofs = slo_info->raw_data.length();
}
return RGWPutObj_ObjStore::get_params();
get_rmattrs_from_headers(s, CONT_PUT_ATTR_PREFIX, CONT_REMOVE_ATTR_PREFIX,
rmattr_names);
- placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");
+ placement_rule.init(s->info.env->get("HTTP_X_STORAGE_POLICY", ""), s->info.storage_class);
return get_swift_versioning_settings(s, swift_ver_location);
}
return r;
}
- placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");
dlo_manifest = s->info.env->get("HTTP_X_OBJECT_MANIFEST");
return 0;
{
map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_CONTENT_TYPE);
if (iter != attrs.end()) {
- content_type = iter->second.c_str();
+ content_type = rgw_bl_str(iter->second);
}
}
static void dump_object_metadata(struct req_state * const s,
- map<string, bufferlist> attrs)
+ const map<string, bufferlist>& attrs)
{
map<string, string> response_attrs;
const auto aiter = rgw_to_http_attrs.find(name);
if (aiter != std::end(rgw_to_http_attrs)) {
- response_attrs[aiter->second] = kv.second.c_str();
+ response_attrs[aiter->second] = rgw_bl_str(kv.second);
} else if (strcmp(name, RGW_ATTR_SLO_UINDICATOR) == 0) {
- // this attr has an extra length prefix from ::encode() in prior versions
+ // this attr has an extra length prefix from encode() in prior versions
dump_header(s, "X-Object-Meta-Static-Large-Object", "True");
} else if (strncmp(name, RGW_ATTR_META_PREFIX,
sizeof(RGW_ATTR_META_PREFIX)-1) == 0) {
if (iter != std::end(attrs)) {
utime_t delete_at;
try {
- ::decode(delete_at, iter->second);
+ decode(delete_at, iter->second);
if (!delete_at.is_zero()) {
dump_header(s, "X-Delete-At", delete_at.sec());
}
} else {
auto iter = attrs.find(RGW_ATTR_ETAG);
if (iter != attrs.end()) {
- dump_etag(s, iter->second);
+ dump_etag(s, iter->second.to_str());
}
}
<< R"(<!DOCTYPE cross-domain-policy SYSTEM )"
<< R"("http://www.adobe.com/xml/dtds/cross-domain-policy.dtd" >)" << "\n"
<< R"(<cross-domain-policy>)" << "\n"
- << g_conf->rgw_cross_domain_policy << "\n"
+ << g_conf()->rgw_cross_domain_policy << "\n"
<< R"(</cross-domain-policy>)";
dump_body(s, ss.str());
s->formatter->close_section();
}
else {
- pair.second.list_data(*(s->formatter), *(s->cct->_conf), *store);
+ pair.second.list_data(*(s->formatter), s->cct->_conf, *store);
}
}
}
void RGWInfo_ObjStore_SWIFT::list_swift_data(Formatter& formatter,
- const md_config_t& config,
+ const ConfigProxy& config,
RGWRados& store)
{
formatter.open_object_section("swift");
- formatter.dump_int("max_file_size", config.rgw_max_put_size);
+ formatter.dump_int("max_file_size", config->rgw_max_put_size);
formatter.dump_int("container_listing_limit", RGW_LIST_BUCKETS_LIMIT_MAX);
string ceph_version(CEPH_GIT_NICE_VER);
formatter.dump_string("version", ceph_version);
const size_t max_attr_name_len = \
- g_conf->get_val<size_t>("rgw_max_attr_name_len");
+ g_conf().get_val<Option::size_t>("rgw_max_attr_name_len");
if (max_attr_name_len) {
const size_t meta_name_limit = \
max_attr_name_len - strlen(RGW_ATTR_PREFIX RGW_AMZ_META_PREFIX);
formatter.dump_int("max_meta_name_length", meta_name_limit);
}
- const size_t meta_value_limit = g_conf->get_val<size_t>("rgw_max_attr_size");
+ const size_t meta_value_limit = g_conf().get_val<Option::size_t>("rgw_max_attr_size");
if (meta_value_limit) {
formatter.dump_int("max_meta_value_length", meta_value_limit);
}
const size_t meta_num_limit = \
- g_conf->get_val<size_t>("rgw_max_attrs_num_in_req");
+ g_conf().get_val<uint64_t>("rgw_max_attrs_num_in_req");
if (meta_num_limit) {
formatter.dump_int("max_meta_count", meta_num_limit);
}
formatter.open_array_section("policies");
- RGWZoneGroup& zonegroup = store.get_zonegroup();
+ const RGWZoneGroup& zonegroup = store.svc.zone->get_zonegroup();
for (const auto& placement_targets : zonegroup.placement_targets) {
formatter.open_object_section("policy");
- if (placement_targets.second.name.compare(zonegroup.default_placement) == 0)
+ if (placement_targets.second.name.compare(zonegroup.default_placement.name) == 0)
formatter.dump_bool("default", true);
formatter.dump_string("name", placement_targets.second.name.c_str());
formatter.close_section();
}
void RGWInfo_ObjStore_SWIFT::list_tempauth_data(Formatter& formatter,
- const md_config_t& config,
+ const ConfigProxy& config,
RGWRados& store)
{
formatter.open_object_section("tempauth");
formatter.close_section();
}
void RGWInfo_ObjStore_SWIFT::list_tempurl_data(Formatter& formatter,
- const md_config_t& config,
+ const ConfigProxy& config,
RGWRados& store)
{
formatter.open_object_section("tempurl");
}
void RGWInfo_ObjStore_SWIFT::list_slo_data(Formatter& formatter,
- const md_config_t& config,
+ const ConfigProxy& config,
RGWRados& store)
{
formatter.open_object_section("slo");
- formatter.dump_int("max_manifest_segments", config.rgw_max_slo_entries);
+ formatter.dump_int("max_manifest_segments", config->rgw_max_slo_entries);
formatter.close_section();
}
/* Need to get user info of bucket owner. */
RGWBucketInfo bucket_info;
- int ret = store->get_bucket_info(*static_cast<RGWObjectCtx *>(s->obj_ctx),
+ int ret = store->get_bucket_info(*s->sysobj_ctx,
bucket_tenant, bucket_name,
bucket_info, nullptr);
if (ret < 0) {
return ret;
}
- if (s->cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20)) {
+ if (s->cct->_conf->subsys.should_gather<ceph_subsys_rgw, 20>()) {
ldout(s->cct, 20) << "read part header -- part.name="
<< part.name << dendl;
class RGWMovedPermanently: public RGWOp {
const std::string location;
public:
- RGWMovedPermanently(const std::string& location)
+ explicit RGWMovedPermanently(const std::string& location)
: location(location) {
}
end_header(s, this);
}
- const string name() override {
+ const char* name() const override {
return "RGWMovedPermanently";
}
};
public:
/* Taking prefix_override by value to leverage std::string r-value ref
* ctor and thus avoid extra memory copying/increasing ref counter. */
- RGWWebsiteListing(std::string prefix_override)
+ explicit RGWWebsiteListing(std::string prefix_override)
: prefix_override(std::move(prefix_override)) {
}
};
/* First, get attrset of the object we'll try to retrieve. */
RGWObjectCtx& obj_ctx = *static_cast<RGWObjectCtx *>(s->obj_ctx);
- obj_ctx.obj.set_atomic(obj);
- obj_ctx.obj.set_prefetch_data(obj);
+ obj_ctx.set_atomic(obj);
+ obj_ctx.set_prefetch_data(obj);
RGWObjState* state = nullptr;
if (store->get_obj_state(&obj_ctx, s->bucket_info, obj, &state, false) < 0) {
rgw_obj obj(s->bucket, index);
RGWObjectCtx& obj_ctx = *static_cast<RGWObjectCtx *>(s->obj_ctx);
- obj_ctx.obj.set_atomic(obj);
- obj_ctx.obj.set_prefetch_data(obj);
+ obj_ctx.set_atomic(obj);
+ obj_ctx.set_prefetch_data(obj);
RGWObjState* state = nullptr;
if (store->get_obj_state(&obj_ctx, s->bucket_info, obj, &state, false) < 0) {
}
-int RGWHandler_REST_SWIFT::authorize()
+int RGWHandler_REST_SWIFT::authorize(const DoutPrefixProvider *dpp)
{
- return rgw::auth::Strategy::apply(auth_strategy, s);
+ return rgw::auth::Strategy::apply(dpp, auth_strategy, s);
}
int RGWHandler_REST_SWIFT::postauth_init()
for (size_t i = 0; i < len; ++i, ++s) {
if (*(unsigned char *)s == 0xff)
return -ERR_INVALID_BUCKET_NAME;
+ if (*(unsigned char *)s == '/')
+ return -ERR_INVALID_BUCKET_NAME;
}
return 0;
}
if ('\0' == req_name[0]) {
- return g_conf->rgw_swift_url_prefix == "/" ? -ERR_BAD_URL : 0;
+ return g_conf()->rgw_swift_url_prefix == "/" ? -ERR_BAD_URL : 0;
}
req = req_name;
size_t pos = req.find('/');
- if (std::string::npos != pos && g_conf->rgw_swift_url_prefix != "/") {
- bool cut_url = g_conf->rgw_swift_url_prefix.length();
+ if (std::string::npos != pos && g_conf()->rgw_swift_url_prefix != "/") {
+ bool cut_url = g_conf()->rgw_swift_url_prefix.length();
first = req.substr(0, pos);
- if (first.compare(g_conf->rgw_swift_url_prefix) == 0) {
+ if (first.compare(g_conf()->rgw_swift_url_prefix) == 0) {
if (cut_url) {
/* Rewind to the "v1/..." part. */
next_tok(req, first, '/');
}
}
- } else if (req.compare(g_conf->rgw_swift_url_prefix) == 0) {
+ } else if (req.compare(g_conf()->rgw_swift_url_prefix) == 0) {
s->formatter = new RGWFormatter_Plain;
return -ERR_BAD_URL;
} else {
}
std::string tenant_path;
- if (! g_conf->rgw_swift_tenant_name.empty()) {
+ if (! g_conf()->rgw_swift_tenant_name.empty()) {
tenant_path = "/AUTH_";
- tenant_path.append(g_conf->rgw_swift_tenant_name);
+ tenant_path.append(g_conf()->rgw_swift_tenant_name);
}
/* verify that the request_uri conforms with what's expected */
- char buf[g_conf->rgw_swift_url_prefix.length() + 16 + tenant_path.length()];
+ char buf[g_conf()->rgw_swift_url_prefix.length() + 16 + tenant_path.length()];
int blen;
- if (g_conf->rgw_swift_url_prefix == "/") {
+ if (g_conf()->rgw_swift_url_prefix == "/") {
blen = sprintf(buf, "/v1%s", tenant_path.c_str());
} else {
blen = sprintf(buf, "/%s/v1%s",
- g_conf->rgw_swift_url_prefix.c_str(), tenant_path.c_str());
+ g_conf()->rgw_swift_url_prefix.c_str(), tenant_path.c_str());
}
if (strncmp(reqbuf, buf, blen) != 0) {
next_tok(req, ver, '/');
- if (!tenant_path.empty() || g_conf->rgw_swift_account_in_url) {
+ if (!tenant_path.empty() || g_conf()->rgw_swift_account_in_url) {
string account_name;
next_tok(req, account_name, '/');
s->op = OP_PUT;
}
+ s->info.storage_class = s->info.env->get("HTTP_X_OBJECT_STORAGE_CLASS", "");
+
return RGWHandler_REST::init(store, s, cio);
}