#option for RGW
option(WITH_RADOSGW "Rados Gateway is enabled" ON)
-option(WITH_RADOSGW_FCGI_FRONTEND "Rados Gateway's FCGI frontend is enabled" OFF)
option(WITH_RADOSGW_BEAST_FRONTEND "Rados Gateway's Beast frontend is enabled" ON)
option(WITH_RADOSGW_BEAST_OPENSSL "Rados Gateway's Beast frontend uses OpenSSL" ON)
option(WITH_RADOSGW_AMQP_ENDPOINT "Rados Gateway's pubsub support for AMQP push endpoint" ON)
if(WITH_RADOSGW)
find_package(EXPAT REQUIRED)
- if(WITH_RADOSGW_FCGI_FRONTEND)
- find_package(fcgi REQUIRED)
- endif()
find_package(OATH REQUIRED)
# https://curl.haxx.se/docs/install.html mentions the
+++ /dev/null
-# CMake module to search for FastCGI headers
-#
-# If it's found it sets FCGI_FOUND to TRUE
-# and following variables are set:
-# FCGI_INCLUDE_DIR
-# FCGI_LIBRARY
-find_path(FCGI_INCLUDE_DIR
- fcgio.h
- PATHS
- /usr/include
- /usr/local/include
- /usr/include/fastcgi)
-find_library(FCGI_LIBRARY NAMES fcgi libfcgi PATHS
- /usr/local/lib
- /usr/lib)
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(fcgi DEFAULT_MSG FCGI_LIBRARY FCGI_INCLUDE_DIR)
-
-mark_as_advanced(FCGI_LIBRARY FCGI_INCLUDE_DIR)
:Default: ``10000``
-``rgw_socket_path``
-
-:Description: The socket path for the domain socket. ``FastCgiExternalServer``
- uses this socket. If you do not specify a socket path, Ceph
- Object Gateway will not run as an external server. The path you
- specify here must be the same as the path specified in the
- ``rgw.conf`` file.
-
-:Type: String
-:Default: N/A
-
-``rgw_fcgi_socket_backlog``
-
-:Description: The socket backlog for fcgi.
-:Type: Integer
-:Default: ``1024``
-
-``rgw_host``
-
-:Description: The host for the Ceph Object Gateway instance. Can be an IP
- address or a hostname.
-
-:Type: String
-:Default: ``0.0.0.0``
-
-
-``rgw_port``
-
-:Description: Port the instance listens for requests. If not specified,
- Ceph Object Gateway runs external FastCGI.
-
-:Type: String
-:Default: None
-
-
``rgw_dns_name``
:Description: The DNS name of the served domain. See also the ``hostnames`` setting within regions.
+++ /dev/null
-FastCgiExternalServer /var/www/s3gw.fcgi -socket /tmp/radosgw.sock
-
-
-<VirtualHost *:80>
-
- ServerName {fqdn}
- <!--Remove the comment. Add a server alias with *.{fqdn} for S3 subdomains-->
- <!--ServerAlias *.{fqdn}-->
- ServerAdmin {email.address}
- DocumentRoot /var/www
- RewriteEngine On
- RewriteRule ^/([a-zA-Z0-9-_.]*)([/]?.*) /s3gw.fcgi?page=$1¶ms=$2&%{QUERY_STRING} [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
-
- <IfModule mod_fastcgi.c>
- <Directory /var/www>
- Options +ExecCGI
- AllowOverride All
- SetHandler fastcgi-script
- Order allow,deny
- Allow from all
- AuthBasicAuthoritative Off
- </Directory>
- </IfModule>
-
- AllowEncodedSlashes On
- ErrorLog /var/log/apache2/error.log
- CustomLog /var/log/apache2/access.log combined
- ServerSignature Off
-
-</VirtualHost>
\ No newline at end of file
see_also:
- rgw_cache_enabled
with_legacy: true
-- name: rgw_socket_path
- type: str
- level: advanced
- desc: RGW FastCGI socket path (for FastCGI over Unix domain sockets).
- services:
- - rgw
- see_also:
- - rgw_fcgi_socket_backlog
- with_legacy: true
-- name: rgw_host
- type: str
- level: advanced
- desc: RGW FastCGI host name (for FastCGI over TCP)
- services:
- - rgw
- see_also:
- - rgw_port
- - rgw_fcgi_socket_backlog
- with_legacy: true
-- name: rgw_port
- type: str
- level: basic
- desc: RGW FastCGI port number (for FastCGI over TCP)
- services:
- - rgw
- see_also:
- - rgw_host
- - rgw_fcgi_socket_backlog
- with_legacy: true
- name: rgw_dns_name
type: str
level: advanced
- rgw_enable_ops_log
- rgw_ops_log_socket_path
with_legacy: true
-# socket backlog for fcgi
-- name: rgw_fcgi_socket_backlog
- type: int
- level: advanced
- desc: FastCGI socket connection backlog
- long_desc: 'Size of FastCGI connection backlog. This reflects the maximum number
- of new connection requests that RGW can handle concurrently without dropping any. '
- default: 1024
- services:
- - rgw
- see_also:
- - rgw_host
- - rgw_socket_path
- with_legacy: true
- name: rgw_usage_log_flush_threshold
type: int
level: advanced
/* define if radosgw enabled */
#cmakedefine WITH_RADOSGW
-/* define if radosgw enabled */
-#cmakedefine WITH_RADOSGW_FCGI_FRONTEND
-
/* define if leveldb is enabled */
#cmakedefine WITH_LEVELDB
COMPILE_FLAGS -I${CMAKE_BINARY_DIR}/src/rgw)
-if (WITH_RADOSGW_FCGI_FRONTEND)
- list(APPEND rgw_a_srcs rgw_fcgi.cc)
-endif()
-
add_library(rgw_a STATIC
${rgw_a_srcs}
$<TARGET_OBJECTS:rgw_common>)
rgw_dmclock_sync_scheduler.cc)
set(radosgw_srcs
rgw_loadgen_process.cc)
-if (WITH_RADOSGW_FCGI_FRONTEND)
- list(APPEND radosgw_srcs rgw_fcgi_process.cc)
-endif()
if(WITH_RADOSGW_BEAST_FRONTEND)
list(APPEND radosgw_srcs
cls_log_client cls_timeindex_client neorados_cls_fifo
cls_version_client cls_user_client
global
- ${FCGI_LIBRARY} ${LIB_RESOLV}
+ ${LIB_RESOLV}
${CURL_LIBRARIES} ${EXPAT_LIBRARIES} ${BLKID_LIBRARIES}
${ALLOC_LIBS})
set_target_properties(radosgwd PROPERTIES OUTPUT_NAME radosgw)
cls_rgw_client cls_otp_client cls_lock_client cls_refcount_client
cls_log_client cls_timeindex_client neorados_cls_fifo
cls_version_client cls_user_client
- global ${FCGI_LIBRARY} ${LIB_RESOLV}
+ global ${LIB_RESOLV}
${CURL_LIBRARIES} ${EXPAT_LIBRARIES} ${BLKID_LIBRARIES})
install(TARGETS radosgw-admin DESTINATION bin)
cls_rgw_client cls_otp_client cls_lock_client cls_refcount_client
cls_log_client cls_timeindex_client neorados_cls_fifo
cls_version_client cls_user_client
- global ${FCGI_LIBRARY} ${LIB_RESOLV}
+ global ${LIB_RESOLV}
${CURL_LIBRARIES} ${EXPAT_LIBRARIES} ${BLKID_LIBRARIES})
install(TARGETS radosgw-es DESTINATION bin)
cls_rgw_client cls_otp_client cls_lock_client cls_refcount_client
cls_log_client cls_timeindex_client neorados_cls_fifo
cls_version_client cls_user_client
- global ${FCGI_LIBRARY} ${LIB_RESOLV}
+ global ${LIB_RESOLV}
${CURL_LIBRARIES} ${EXPAT_LIBRARIES})
install(TARGETS radosgw-object-expirer DESTINATION bin)
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab ft=cpp
-
-#include "rgw_fcgi.h"
-#include "acconfig.h"
-
-size_t RGWFCGX::write_data(const char* const buf, const size_t len)
-{
- /* According to the documentation of FCGX_PutStr if there is no error
- * (signalised by negative return value), then always ret == len. */
- const auto ret = FCGX_PutStr(buf, len, fcgx->out);
- if (ret < 0) {
- throw rgw::io::Exception(-ret, std::system_category());
- }
- return ret;
-}
-
-size_t RGWFCGX::read_data(char* const buf, const size_t len)
-{
- const auto ret = FCGX_GetStr(buf, len, fcgx->in);
- if (ret < 0) {
- throw rgw::io::Exception(-ret, std::system_category());
- }
- return ret;
-}
-
-void RGWFCGX::flush()
-{
- txbuf.pubsync();
- FCGX_FFlush(fcgx->out);
-}
-
-int RGWFCGX::init_env(CephContext* const cct)
-{
- env.init(cct, (char **)fcgx->envp);
- return 0;
-}
-
-size_t RGWFCGX::send_status(const int status, const char* const status_name)
-{
- static constexpr size_t STATUS_BUF_SIZE = 128;
-
- char statusbuf[STATUS_BUF_SIZE];
- const auto statuslen = snprintf(statusbuf, sizeof(statusbuf),
- "Status: %d %s\r\n", status, status_name);
-
- return txbuf.sputn(statusbuf, statuslen);
-}
-
-size_t RGWFCGX::send_100_continue()
-{
- const auto sent = send_status(100, "Continue");
- flush();
- return sent;
-}
-
-size_t RGWFCGX::send_header(const std::string_view& name,
- const std::string_view& value)
-{
- static constexpr char HEADER_SEP[] = ": ";
- static constexpr char HEADER_END[] = "\r\n";
-
- size_t sent = 0;
-
- sent += txbuf.sputn(name.data(), name.length());
- sent += txbuf.sputn(HEADER_SEP, sizeof(HEADER_SEP) - 1);
- sent += txbuf.sputn(value.data(), value.length());
- sent += txbuf.sputn(HEADER_END, sizeof(HEADER_END) - 1);
-
- return sent;
-}
-
-size_t RGWFCGX::send_content_length(const uint64_t len)
-{
- static constexpr size_t CONLEN_BUF_SIZE = 128;
-
- char sizebuf[CONLEN_BUF_SIZE];
- const auto sizelen = snprintf(sizebuf, sizeof(sizebuf),
- "Content-Length: %" PRIu64 "\r\n", len);
-
- return txbuf.sputn(sizebuf, sizelen);
-}
-
-size_t RGWFCGX::complete_header()
-{
- static constexpr char HEADER_END[] = "\r\n";
- const size_t sent = txbuf.sputn(HEADER_END, sizeof(HEADER_END) - 1);
-
- flush();
- return sent;
-}
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab ft=cpp
-
-#ifndef CEPH_RGW_FCGI_H
-#define CEPH_RGW_FCGI_H
-
-#include "acconfig.h"
-#include <fcgiapp.h>
-
-#include "rgw_client_io.h"
-
-struct FCGX_Request;
-
-class RGWFCGX : public rgw::io::RestfulClient,
- public rgw::io::BuffererSink {
- FCGX_Request *fcgx;
- RGWEnv env;
-
- rgw::io::StaticOutputBufferer<> txbuf;
-
- size_t read_data(char* buf, size_t len);
- size_t write_data(const char* buf, size_t len) override;
-
-public:
- explicit RGWFCGX(FCGX_Request* const fcgx)
- : fcgx(fcgx),
- txbuf(*this) {
- }
-
- int init_env(CephContext* cct) override;
- size_t send_status(int status, const char* status_name) override;
- size_t send_100_continue() override;
- size_t send_header(const std::string_view& name,
- const std::string_view& value) override;
- size_t send_content_length(uint64_t len) override;
- size_t complete_header() override;
-
- size_t recv_body(char* buf, size_t max) override {
- return read_data(buf, max);
- }
-
- size_t send_body(const char* buf, size_t len) override {
- return write_data(buf, len);
- }
-
- void flush() override;
-
- RGWEnv& get_env() noexcept override {
- return env;
- }
-
- size_t complete_request() override {
- return 0;
- }
-};
-
-#endif
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab ft=cpp
-
-#include "common/errno.h"
-#include "common/Throttle.h"
-#include "common/WorkQueue.h"
-
-#include "rgw_rest.h"
-#include "rgw_frontend.h"
-#include "rgw_request.h"
-#include "rgw_process.h"
-#include "rgw_loadgen.h"
-#include "rgw_client_io.h"
-#include "rgw_client_io_filters.h"
-
-#define dout_subsys ceph_subsys_rgw
-
-void RGWFCGXProcess::run()
-{
- string socket_path;
- string socket_port;
- string socket_host;
- int socket_backlog;
-
- conf->get_val("socket_path", "", &socket_path);
- conf->get_val("socket_port", g_conf()->rgw_port, &socket_port);
- conf->get_val("socket_host", g_conf()->rgw_host, &socket_host);
- socket_backlog = g_conf()->rgw_fcgi_socket_backlog;
-
- if (socket_path.empty() && socket_port.empty() && socket_host.empty()) {
- socket_path = g_conf()->rgw_socket_path;
- if (socket_path.empty()) {
- dout(0) << "ERROR: no socket server point defined, cannot "
- "start fcgi frontend" << dendl;
- return;
- }
- }
-
- if (!socket_path.empty()) {
- string path_str = socket_path;
-
- /* this is necessary, as FCGX_OpenSocket might not return an
- * error, but rather ungracefully exit */
- int fd = open(path_str.c_str(), O_CREAT, 0644);
- if (fd < 0) {
- int err = errno;
- /* ENXIO is actually expected, we'll get that if we try to open
- * a unix domain socket */
- if (err != ENXIO) {
- dout(0) << "ERROR: cannot create socket: path=" << path_str
- << " error=" << cpp_strerror(err) << dendl;
- return;
- }
- } else {
- close(fd);
- }
-
- const char *path = path_str.c_str();
- sock_fd = FCGX_OpenSocket(path, socket_backlog);
- if (sock_fd < 0) {
- dout(0) << "ERROR: FCGX_OpenSocket (" << path << ") returned "
- << sock_fd << dendl;
- return;
- }
- if (chmod(path, 0777) < 0) {
- dout(0) << "WARNING: couldn't set permissions on unix domain socket"
- << dendl;
- }
- } else if (!socket_port.empty()) {
- string bind = socket_host + ":" + socket_port;
- sock_fd = FCGX_OpenSocket(bind.c_str(), socket_backlog);
- if (sock_fd < 0) {
- dout(0) << "ERROR: FCGX_OpenSocket (" << bind.c_str() << ") returned "
- << sock_fd << dendl;
- return;
- }
- }
-
- m_tp.start();
-
- FCGX_Request fcgx_reqs[max_connections];
-
- QueueRing<FCGX_Request*> qr(max_connections);
- for (int i = 0; i < max_connections; i++) {
- FCGX_Request* fcgx = &fcgx_reqs[i];
- FCGX_InitRequest(fcgx, sock_fd, 0);
- qr.enqueue(fcgx);
- }
-
- for (;;) {
- RGWFCGXRequest* req = new RGWFCGXRequest(store->getRados()->get_new_req_id(), &qr);
- dout(10) << "allocated request req=" << hex << req << dec << dendl;
- req_throttle.get(1);
- int ret = FCGX_Accept_r(req->fcgx);
- if (ret < 0) {
- delete req;
- dout(0) << "ERROR: FCGX_Accept_r returned " << ret << dendl;
- req_throttle.put(1);
- break;
- }
- req_wq.queue(req);
- }
-
- m_tp.drain(&req_wq);
- m_tp.stop();
-
- dout(20) << "cleaning up fcgx connections" << dendl;
-
- for (int i = 0; i < max_connections; i++) {
- FCGX_Finish_r(&fcgx_reqs[i]);
- }
-} /* RGWFCGXProcess::run */
-
-void RGWFCGXProcess::handle_request(RGWRequest* r)
-{
- RGWFCGXRequest* const req = static_cast<RGWFCGXRequest*>(r);
-
- RGWFCGX fcgxfe(req->fcgx);
- auto real_client_io = rgw::io::add_reordering(
- rgw::io::add_buffering(cct,
- rgw::io::add_chunking(
- &fcgxfe)));
- RGWRestfulIO client_io(cct, &real_client_io);
-
-
- int ret = process_request(store, rest, req, uri_prefix,
- *auth_registry, &client_io, olog,
- null_yield, nullptr);
- if (ret < 0) {
- /* we don't really care about return code */
- dout(20) << "process_request() returned " << ret << dendl;
- }
-
- FCGX_Finish_r(req->fcgx);
-
- delete req;
-} /* RGWFCGXProcess::handle_request */
}
}; /* RGWProcessFrontend */
-class RGWFCGXFrontend : public RGWProcessFrontend {
-public:
- RGWFCGXFrontend(RGWProcessEnv& pe, RGWFrontendConfig* _conf)
- : RGWProcessFrontend(pe, _conf) {}
-
- int init() override {
- pprocess = new RGWFCGXProcess(g_ceph_context, &env,
- g_conf()->rgw_thread_pool_size, conf);
- return 0;
- }
-}; /* RGWFCGXFrontend */
-
class RGWLoadGenFrontend : public RGWProcessFrontend, public DoutPrefixProvider {
public:
RGWLoadGenFrontend(RGWProcessEnv& pe, RGWFrontendConfig *_conf)
static void handle_sigterm(int signum)
{
dout(1) << __func__ << dendl;
-#if defined(WITH_RADOSGW_FCGI_FRONTEND)
- FCGX_ShutdownPending();
-#endif
// send a signal to make fcgi's accept(2) wake up. unfortunately the
// initial signal often isn't sufficient because we race with accept's
rgw_http_client_init(g_ceph_context);
rgw_kmip_client_init(*new RGWKMIPManagerImpl(g_ceph_context));
-#if defined(WITH_RADOSGW_FCGI_FRONTEND)
- FCGX_Init();
-#endif
-
const DoutPrefix dp(cct.get(), dout_subsys, "rgw main: ");
rgw::sal::Store* store =
StoreManager::get_storage(&dp, g_ceph_context,
fe = new RGWAsioFrontend(env, config, sched_ctx);
}
#endif /* WITH_RADOSGW_BEAST_FRONTEND */
-#if defined(WITH_RADOSGW_FCGI_FRONTEND)
- else if (framework == "fastcgi" || framework == "fcgi") {
- framework = "fastcgi";
- std::string uri_prefix;
- config->get_val("prefix", "", &uri_prefix);
- RGWProcessEnv fcgi_pe = { store, &rest, olog, 0, uri_prefix, auth_registry };
-
- fe = new RGWFCGXFrontend(fcgi_pe, config);
- }
-#endif /* WITH_RADOSGW_FCGI_FRONTEND */
service_map_meta["frontend_type#" + stringify(fe_count)] = framework;
service_map_meta["frontend_config#" + stringify(fe_count)] = config->get_config();
}
}; /* RGWProcess */
-class RGWFCGXProcess : public RGWProcess {
- int max_connections;
-public:
-
- /* have a bit more connections than threads so that requests are
- * still accepted even if we're still processing older requests */
- RGWFCGXProcess(CephContext* const cct,
- RGWProcessEnv* const pe,
- const int num_threads,
- RGWFrontendConfig* const conf)
- : RGWProcess(cct, pe, num_threads, conf),
- max_connections(num_threads + (num_threads >> 3)) {
- }
-
- void run() override;
- void handle_request(const DoutPrefixProvider *dpp, RGWRequest* req) override;
-};
-
class RGWProcessControlThread : public Thread {
RGWProcess *pprocess;
public:
#include "rgw_acl.h"
#include "rgw_user.h"
#include "rgw_op.h"
-#if defined(WITH_RADOSGW_FCGI_FRONTEND)
-#include "rgw_fcgi.h"
-#endif
#include "common/QueueRing.h"
}
}; /* RGWRequest */
-#if defined(WITH_RADOSGW_FCGI_FRONTEND)
-struct RGWFCGXRequest : public RGWRequest {
- FCGX_Request *fcgx;
- QueueRing<FCGX_Request *> *qr;
-
- RGWFCGXRequest(uint64_t req_id, QueueRing<FCGX_Request *> *_qr)
- : RGWRequest(req_id), qr(_qr) {
- qr->dequeue(&fcgx);
- }
-
- ~RGWFCGXRequest() override {
- FCGX_Finish_r(fcgx);
- qr->enqueue(fcgx);
- }
-};
-#endif
-
struct RGWLoadGenRequest : public RGWRequest {
string method;
string resource;
add_executable(ceph_test_librgw_file
librgw_file.cc
)
-if(WITH_RADOSGW_FCGI_FRONTEND)
-target_include_directories(ceph_test_librgw_file SYSTEM PRIVATE ${FCGI_INCLUDE_DIR})
-endif(WITH_RADOSGW_FCGI_FRONTEND)
target_link_libraries(ceph_test_librgw_file
rgw
librados
librgw_file_nfsns.cc
)
target_include_directories(ceph_test_librgw_file_nfsns SYSTEM PRIVATE "${CMAKE_SOURCE_DIR}/src/rgw")
-if(WITH_RADOSGW_FCGI_FRONTEND)
-target_include_directories(ceph_test_librgw_file_nfsns SYSTEM PRIVATE ${FCGI_INCLUDE_DIR})
-endif(WITH_RADOSGW_FCGI_FRONTEND)
target_link_libraries(ceph_test_librgw_file_nfsns
rgw
librados