]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_main.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / rgw / rgw_main.cc
CommitLineData
7c673cae 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
7c673cae 3
f67539c2 4#include <boost/intrusive/list.hpp>
7c673cae
FG
5#include "common/ceph_argparse.h"
6#include "global/global_init.h"
7#include "global/signal_handler.h"
8#include "common/config.h"
9#include "common/errno.h"
10#include "common/Timer.h"
11#include "common/safe_io.h"
11fdf7f2 12#include "common/TracepointProvider.h"
f67539c2 13#include "common/openssl_opts_handler.h"
9f95a23c 14#include "common/numa.h"
7c673cae
FG
15#include "include/compat.h"
16#include "include/str_list.h"
224ce89b 17#include "include/stringify.h"
7c673cae 18#include "rgw_common.h"
f67539c2 19#include "rgw_sal.h"
7c673cae
FG
20#include "rgw_period_pusher.h"
21#include "rgw_realm_reloader.h"
22#include "rgw_rest.h"
23#include "rgw_rest_s3.h"
24#include "rgw_rest_swift.h"
25#include "rgw_rest_admin.h"
20effc67 26#include "rgw_rest_info.h"
7c673cae
FG
27#include "rgw_rest_usage.h"
28#include "rgw_rest_user.h"
29#include "rgw_rest_bucket.h"
30#include "rgw_rest_metadata.h"
31#include "rgw_rest_log.h"
7c673cae
FG
32#include "rgw_rest_config.h"
33#include "rgw_rest_realm.h"
11fdf7f2 34#include "rgw_rest_sts.h"
20effc67 35#include "rgw_rest_ratelimit.h"
7c673cae
FG
36#include "rgw_swift_auth.h"
37#include "rgw_log.h"
38#include "rgw_tools.h"
39#include "rgw_resolve.h"
7c673cae
FG
40#include "rgw_request.h"
41#include "rgw_process.h"
42#include "rgw_frontend.h"
94b18763 43#include "rgw_http_client_curl.h"
f67539c2
TL
44#include "rgw_kmip_client.h"
45#include "rgw_kmip_client_impl.h"
11fdf7f2 46#include "rgw_perf_counters.h"
eafe8130
TL
47#ifdef WITH_RADOSGW_AMQP_ENDPOINT
48#include "rgw_amqp.h"
49#endif
9f95a23c
TL
50#ifdef WITH_RADOSGW_KAFKA_ENDPOINT
51#include "rgw_kafka.h"
52#endif
7c673cae 53#include "rgw_asio_frontend.h"
11fdf7f2 54#include "rgw_dmclock_scheduler_ctx.h"
f67539c2
TL
55#ifdef WITH_RADOSGW_LUA_PACKAGES
56#include "rgw_lua.h"
57#endif
20effc67
TL
58#ifdef WITH_RADOSGW_DBSTORE
59#include "rgw_sal_dbstore.h"
60#endif
7c673cae 61
11fdf7f2 62#include "services/svc_zone.h"
7c673cae
FG
63
64#ifdef HAVE_SYS_PRCTL_H
65#include <sys/prctl.h>
66#endif
67
68#define dout_subsys ceph_subsys_rgw
69
20effc67
TL
70using namespace std;
71
11fdf7f2
TL
72namespace {
73TracepointProvider::Traits rgw_op_tracepoint_traits("librgw_op_tp.so",
74 "rgw_op_tracing");
75TracepointProvider::Traits rgw_rados_tracepoint_traits("librgw_rados_tp.so",
76 "rgw_rados_tracing");
77}
7c673cae
FG
78
79static sig_t sighandler_alrm;
80
81class RGWProcess;
82
83static int signal_fd[2] = {0, 0};
7c673cae
FG
84
85void signal_shutdown()
86{
11fdf7f2
TL
87 int val = 0;
88 int ret = write(signal_fd[0], (char *)&val, sizeof(val));
89 if (ret < 0) {
90 derr << "ERROR: " << __func__ << ": write() returned "
91 << cpp_strerror(errno) << dendl;
7c673cae
FG
92 }
93}
94
95static void wait_shutdown()
96{
97 int val;
98 int r = safe_read_exact(signal_fd[1], &val, sizeof(val));
99 if (r < 0) {
100 derr << "safe_read_exact returned with error" << dendl;
101 }
102}
103
104static int signal_fd_init()
105{
106 return socketpair(AF_UNIX, SOCK_STREAM, 0, signal_fd);
107}
108
109static void signal_fd_finalize()
110{
111 close(signal_fd[0]);
112 close(signal_fd[1]);
113}
114
115static void handle_sigterm(int signum)
116{
117 dout(1) << __func__ << dendl;
7c673cae
FG
118
119 // send a signal to make fcgi's accept(2) wake up. unfortunately the
120 // initial signal often isn't sufficient because we race with accept's
121 // check of the flag wet by ShutdownPending() above.
122 if (signum != SIGUSR1) {
123 signal_shutdown();
124
125 // safety net in case we get stuck doing an orderly shutdown.
126 uint64_t secs = g_ceph_context->_conf->rgw_exit_timeout_secs;
127 if (secs)
128 alarm(secs);
129 dout(1) << __func__ << " set alarm for " << secs << dendl;
130 }
131
132}
133
134static void godown_alarm(int signum)
135{
136 _exit(0);
137}
138
7c673cae
FG
139
140class C_InitTimeout : public Context {
141public:
142 C_InitTimeout() {}
143 void finish(int r) override {
144 derr << "Initialization timeout, failed to initialize" << dendl;
145 exit(1);
146 }
147};
148
149static int usage()
150{
11fdf7f2
TL
151 cout << "usage: radosgw [options...]" << std::endl;
152 cout << "options:\n";
153 cout << " --rgw-region=<region> region in which radosgw runs\n";
154 cout << " --rgw-zone=<zone> zone in which radosgw runs\n";
155 cout << " --rgw-socket-path=<path> specify a unix domain socket path\n";
156 cout << " -m monaddress[:port] connect to specified monitor\n";
157 cout << " --keyring=<path> path to radosgw keyring\n";
158 cout << " --logfile=<logfile> file to log debug output\n";
159 cout << " --debug-rgw=<log-level>/<memory-level> set radosgw debug level\n";
7c673cae
FG
160 generic_server_usage();
161
162 return 0;
163}
164
165static RGWRESTMgr *set_logging(RGWRESTMgr *mgr)
166{
167 mgr->set_logging(true);
168 return mgr;
169}
170
20effc67 171static RGWRESTMgr *rest_filter(rgw::sal::Store* store, int dialect, RGWRESTMgr *orig)
31f18b77
FG
172{
173 RGWSyncModuleInstanceRef sync_module = store->get_sync_module();
94b18763
FG
174 if (sync_module) {
175 return sync_module->get_rest_filter(dialect, orig);
176 } else {
177 return orig;
178 }
31f18b77
FG
179}
180
7c673cae
FG
181/*
182 * start up the RADOS connection and then handle HTTP messages as they come in
183 */
9f95a23c 184int radosgw_Main(int argc, const char **argv)
7c673cae
FG
185{
186 // dout() messages will be sent to stderr, but FCGX wants messages on stdout
187 // Redirect stderr to stdout.
188 TEMP_FAILURE_RETRY(close(STDERR_FILENO));
189 if (TEMP_FAILURE_RETRY(dup2(STDOUT_FILENO, STDERR_FILENO)) < 0) {
190 int err = errno;
191 cout << "failed to redirect stderr to stdout: " << cpp_strerror(err)
192 << std::endl;
193 return ENOSYS;
194 }
195
196 /* alternative default for module */
11fdf7f2
TL
197 map<string,string> defaults = {
198 { "debug_rgw", "1/5" },
199 { "keyring", "$rgw_data/keyring" },
20effc67
TL
200 { "objecter_inflight_ops", "24576" },
201 // require a secure mon connection by default
202 { "ms_mon_client_mode", "secure" },
203 { "auth_client_required", "cephx" }
11fdf7f2 204 };
7c673cae 205
20effc67 206 auto args = argv_to_vec(argc, argv);
11fdf7f2
TL
207 if (args.empty()) {
208 cerr << argv[0] << ": -h or --help for usage" << std::endl;
209 exit(1);
210 }
211 if (ceph_argparse_need_usage(args)) {
212 usage();
213 exit(0);
214 }
7c673cae 215
7c673cae 216 int flags = CINIT_FLAG_UNPRIVILEGED_DAEMON_DEFAULTS;
1911f103
TL
217 // Prevent global_init() from dropping permissions until frontends can bind
218 // privileged ports
219 flags |= CINIT_FLAG_DEFER_DROP_PRIVILEGES;
220
9f95a23c 221 auto cct = global_init(&defaults, args, CEPH_ENTITY_TYPE_CLIENT,
f67539c2 222 CODE_ENVIRONMENT_DAEMON, flags);
9f95a23c
TL
223
224 // First, let's determine which frontends are configured.
7c673cae 225 list<string> frontends;
9f95a23c
TL
226 string rgw_frontends_str = g_conf().get_val<string>("rgw_frontends");
227 g_conf().early_expand_meta(rgw_frontends_str, &cerr);
228 get_str_list(rgw_frontends_str, ",", frontends);
7c673cae
FG
229 multimap<string, RGWFrontendConfig *> fe_map;
230 list<RGWFrontendConfig *> configs;
231 if (frontends.empty()) {
20effc67 232 frontends.push_back("beast");
7c673cae
FG
233 }
234 for (list<string>::iterator iter = frontends.begin(); iter != frontends.end(); ++iter) {
235 string& f = *iter;
236
20effc67 237 if (f.find("beast") != string::npos) {
7c673cae
FG
238 if (f.find("port") != string::npos) {
239 // check for the most common ws problems
240 if ((f.find("port=") == string::npos) ||
241 (f.find("port= ") != string::npos)) {
91327a77
AA
242 derr << "WARNING: radosgw frontend config found unexpected spacing around 'port' "
243 << "(ensure frontend port parameter has the form 'port=80' with no spaces "
7c673cae
FG
244 << "before or after '=')" << dendl;
245 }
246 }
247 }
248
249 RGWFrontendConfig *config = new RGWFrontendConfig(f);
250 int r = config->init();
251 if (r < 0) {
252 delete config;
253 cerr << "ERROR: failed to init config: " << f << std::endl;
254 return EINVAL;
255 }
256
257 configs.push_back(config);
258
259 string framework = config->get_framework();
260 fe_map.insert(pair<string, RGWFrontendConfig*>(framework, config));
261 }
262
9f95a23c
TL
263 int numa_node = g_conf().get_val<int64_t>("rgw_numa_node");
264 size_t numa_cpu_set_size = 0;
265 cpu_set_t numa_cpu_set;
266
267 if (numa_node >= 0) {
268 int r = get_numa_node_cpu_set(numa_node, &numa_cpu_set_size, &numa_cpu_set);
269 if (r < 0) {
270 dout(1) << __func__ << " unable to determine rgw numa node " << numa_node
271 << " CPUs" << dendl;
272 numa_node = -1;
273 } else {
274 r = set_cpu_affinity_all_threads(numa_cpu_set_size, &numa_cpu_set);
275 if (r < 0) {
276 derr << __func__ << " failed to set numa affinity: " << cpp_strerror(r)
277 << dendl;
278 }
279 }
280 } else {
281 dout(1) << __func__ << " not setting numa affinity" << dendl;
282 }
7c673cae 283
7c673cae 284 // maintain existing region root pool for new multisite objects
11fdf7f2
TL
285 if (!g_conf()->rgw_region_root_pool.empty()) {
286 const char *root_pool = g_conf()->rgw_region_root_pool.c_str();
287 if (g_conf()->rgw_zonegroup_root_pool.empty()) {
288 g_conf().set_val_or_die("rgw_zonegroup_root_pool", root_pool);
7c673cae 289 }
11fdf7f2
TL
290 if (g_conf()->rgw_period_root_pool.empty()) {
291 g_conf().set_val_or_die("rgw_period_root_pool", root_pool);
7c673cae 292 }
11fdf7f2
TL
293 if (g_conf()->rgw_realm_root_pool.empty()) {
294 g_conf().set_val_or_die("rgw_realm_root_pool", root_pool);
7c673cae
FG
295 }
296 }
297
298 // for region -> zonegroup conversion (must happen before common_init_finish())
11fdf7f2
TL
299 if (!g_conf()->rgw_region.empty() && g_conf()->rgw_zonegroup.empty()) {
300 g_conf().set_val_or_die("rgw_zonegroup", g_conf()->rgw_region.c_str());
7c673cae
FG
301 }
302
11fdf7f2 303 if (g_conf()->daemonize) {
7c673cae
FG
304 global_init_daemonize(g_ceph_context);
305 }
9f95a23c 306 ceph::mutex mutex = ceph::make_mutex("main");
7c673cae
FG
307 SafeTimer init_timer(g_ceph_context, mutex);
308 init_timer.init();
9f95a23c 309 mutex.lock();
11fdf7f2 310 init_timer.add_event_after(g_conf()->rgw_init_timeout, new C_InitTimeout);
9f95a23c 311 mutex.unlock();
7c673cae 312
f67539c2
TL
313 ceph::crypto::init_openssl_engine_once();
314
7c673cae
FG
315 common_init_finish(g_ceph_context);
316
11fdf7f2
TL
317 init_async_signal_handler();
318 register_async_signal_handler(SIGHUP, sighup_handler);
319
320 TracepointProvider::initialize<rgw_rados_tracepoint_traits>(g_ceph_context);
321 TracepointProvider::initialize<rgw_op_tracepoint_traits>(g_ceph_context);
322
20effc67
TL
323 const DoutPrefix dp(cct.get(), dout_subsys, "rgw main: ");
324 int r = rgw_tools_init(&dp, g_ceph_context);
7c673cae
FG
325 if (r < 0) {
326 derr << "ERROR: unable to initialize rgw tools" << dendl;
327 return -r;
328 }
329
330 rgw_init_resolver();
94b18763 331 rgw::curl::setup_curl(fe_map);
11fdf7f2 332 rgw_http_client_init(g_ceph_context);
f67539c2 333 rgw_kmip_client_init(*new RGWKMIPManagerImpl(g_ceph_context));
11fdf7f2 334
20effc67
TL
335 lsubdout(cct, rgw, 1) << "rgw_d3n: rgw_d3n_l1_local_datacache_enabled=" << cct->_conf->rgw_d3n_l1_local_datacache_enabled << dendl;
336 if (cct->_conf->rgw_d3n_l1_local_datacache_enabled) {
337 lsubdout(cct, rgw, 1) << "rgw_d3n: rgw_d3n_l1_datacache_persistent_path='" << cct->_conf->rgw_d3n_l1_datacache_persistent_path << "'" << dendl;
338 lsubdout(cct, rgw, 1) << "rgw_d3n: rgw_d3n_l1_datacache_size=" << cct->_conf->rgw_d3n_l1_datacache_size << dendl;
339 lsubdout(cct, rgw, 1) << "rgw_d3n: rgw_d3n_l1_evict_cache_on_start=" << cct->_conf->rgw_d3n_l1_evict_cache_on_start << dendl;
340 lsubdout(cct, rgw, 1) << "rgw_d3n: rgw_d3n_l1_fadvise=" << cct->_conf->rgw_d3n_l1_fadvise << dendl;
341 lsubdout(cct, rgw, 1) << "rgw_d3n: rgw_d3n_l1_eviction_policy=" << cct->_conf->rgw_d3n_l1_eviction_policy << dendl;
342 }
343 bool rgw_d3n_datacache_enabled = cct->_conf->rgw_d3n_l1_local_datacache_enabled;
344 if (rgw_d3n_datacache_enabled && (cct->_conf->rgw_max_chunk_size != cct->_conf->rgw_obj_stripe_size)) {
345 lsubdout(cct, rgw_datacache, 0) << "rgw_d3n: WARNING: D3N DataCache disabling (D3N requires that the chunk_size equals stripe_size)" << dendl;
346 rgw_d3n_datacache_enabled = false;
347 }
348 if (rgw_d3n_datacache_enabled && !cct->_conf->rgw_beast_enable_async) {
349 lsubdout(cct, rgw_datacache, 0) << "rgw_d3n: WARNING: D3N DataCache disabling (D3N requires yield context - rgw_beast_enable_async=true)" << dendl;
350 rgw_d3n_datacache_enabled = false;
351 }
352 lsubdout(cct, rgw, 1) << "D3N datacache enabled: " << rgw_d3n_datacache_enabled << dendl;
353
354 std::string rgw_store = (!rgw_d3n_datacache_enabled) ? "rados" : "d3n";
355
356 const auto& config_store = g_conf().get_val<std::string>("rgw_backend_store");
357#ifdef WITH_RADOSGW_DBSTORE
358 if (config_store == "dbstore") {
359 rgw_store = "dbstore";
360 }
7c673cae
FG
361#endif
362
20effc67
TL
363 rgw::sal::Store* store =
364 StoreManager::get_storage(&dp, g_ceph_context,
365 rgw_store,
11fdf7f2
TL
366 g_conf()->rgw_enable_gc_threads,
367 g_conf()->rgw_enable_lc_threads,
368 g_conf()->rgw_enable_quota_threads,
369 g_conf()->rgw_run_sync_thread,
370 g_conf().get_val<bool>("rgw_dynamic_resharding"),
371 g_conf()->rgw_cache_enabled);
7c673cae 372 if (!store) {
9f95a23c 373 mutex.lock();
7c673cae
FG
374 init_timer.cancel_all_events();
375 init_timer.shutdown();
9f95a23c 376 mutex.unlock();
7c673cae
FG
377
378 derr << "Couldn't init storage provider (RADOS)" << dendl;
379 return EIO;
380 }
381 r = rgw_perf_start(g_ceph_context);
382 if (r < 0) {
383 derr << "ERROR: failed starting rgw perf" << dendl;
384 return -r;
385 }
386
20effc67 387 rgw_rest_init(g_ceph_context, store->get_zone()->get_zonegroup());
7c673cae 388
9f95a23c 389 mutex.lock();
7c673cae
FG
390 init_timer.cancel_all_events();
391 init_timer.shutdown();
9f95a23c 392 mutex.unlock();
7c673cae 393
20effc67 394 rgw_log_usage_init(g_ceph_context, store);
7c673cae
FG
395
396 RGWREST rest;
397
398 list<string> apis;
399
11fdf7f2 400 get_str_list(g_conf()->rgw_enable_apis, apis);
7c673cae
FG
401
402 map<string, bool> apis_map;
403 for (list<string>::iterator li = apis.begin(); li != apis.end(); ++li) {
404 apis_map[*li] = true;
405 }
406
11fdf7f2
TL
407 /* warn about insecure keystone secret config options */
408 if (!(g_ceph_context->_conf->rgw_keystone_admin_token.empty() ||
409 g_ceph_context->_conf->rgw_keystone_admin_password.empty())) {
410 dout(0) << "WARNING: rgw_keystone_admin_token and rgw_keystone_admin_password should be avoided as they can expose secrets. Prefer the new rgw_keystone_admin_token_path and rgw_keystone_admin_password_path options, which read their secrets from files." << dendl;
411 }
412
7c673cae
FG
413 // S3 website mode is a specialization of S3
414 const bool s3website_enabled = apis_map.count("s3website") > 0;
11fdf7f2 415 const bool sts_enabled = apis_map.count("sts") > 0;
92f5a8d4 416 const bool iam_enabled = apis_map.count("iam") > 0;
f67539c2 417 const bool pubsub_enabled = apis_map.count("pubsub") > 0 || apis_map.count("notifications") > 0;
7c673cae 418 // Swift API entrypoint could placed in the root instead of S3
11fdf7f2 419 const bool swift_at_root = g_conf()->rgw_swift_url_prefix == "/";
7c673cae
FG
420 if (apis_map.count("s3") > 0 || s3website_enabled) {
421 if (! swift_at_root) {
20effc67 422 rest.register_default_mgr(set_logging(rest_filter(store, RGW_REST_S3,
92f5a8d4 423 new RGWRESTMgr_S3(s3website_enabled, sts_enabled, iam_enabled, pubsub_enabled))));
7c673cae
FG
424 } else {
425 derr << "Cannot have the S3 or S3 Website enabled together with "
426 << "Swift API placed in the root of hierarchy" << dendl;
427 return EINVAL;
428 }
429 }
430
eafe8130
TL
431 if (pubsub_enabled) {
432#ifdef WITH_RADOSGW_AMQP_ENDPOINT
433 if (!rgw::amqp::init(cct.get())) {
434 dout(1) << "ERROR: failed to initialize AMQP manager" << dendl;
435 }
9f95a23c
TL
436#endif
437#ifdef WITH_RADOSGW_KAFKA_ENDPOINT
438 if (!rgw::kafka::init(cct.get())) {
439 dout(1) << "ERROR: failed to initialize Kafka manager" << dendl;
440 }
eafe8130
TL
441#endif
442 }
443
f67539c2
TL
444 const auto& luarocks_path = g_conf().get_val<std::string>("rgw_luarocks_location");
445 if (luarocks_path.empty()) {
446 store->set_luarocks_path("");
447 } else {
448 store->set_luarocks_path(luarocks_path+"/"+g_conf()->name.to_str());
449 }
450#ifdef WITH_RADOSGW_LUA_PACKAGES
20effc67
TL
451 rgw::sal::RadosStore *rados = dynamic_cast<rgw::sal::RadosStore*>(store);
452 if (rados) { /* Supported for only RadosStore */
453 rgw::lua::packages_t failed_packages;
454 std::string output;
455 r = rgw::lua::install_packages(&dp, rados, null_yield, failed_packages, output);
456 if (r < 0) {
457 dout(1) << "ERROR: failed to install lua packages from allowlist" << dendl;
458 }
459 if (!output.empty()) {
460 dout(10) << "INFO: lua packages installation output: \n" << output << dendl;
461 }
462 for (const auto& p : failed_packages) {
463 dout(5) << "WARNING: failed to install lua package: " << p << " from allowlist" << dendl;
464 }
f67539c2
TL
465 }
466#endif
467
7c673cae
FG
468 if (apis_map.count("swift") > 0) {
469 RGWRESTMgr_SWIFT* const swift_resource = new RGWRESTMgr_SWIFT;
470
11fdf7f2 471 if (! g_conf()->rgw_cross_domain_policy.empty()) {
7c673cae
FG
472 swift_resource->register_resource("crossdomain.xml",
473 set_logging(new RGWRESTMgr_SWIFT_CrossDomain));
474 }
475
476 swift_resource->register_resource("healthcheck",
477 set_logging(new RGWRESTMgr_SWIFT_HealthCheck));
478
479 swift_resource->register_resource("info",
480 set_logging(new RGWRESTMgr_SWIFT_Info));
481
482 if (! swift_at_root) {
11fdf7f2 483 rest.register_resource(g_conf()->rgw_swift_url_prefix,
20effc67 484 set_logging(rest_filter(store, RGW_REST_SWIFT,
31f18b77 485 swift_resource)));
7c673cae 486 } else {
20effc67 487 if (store->get_zone()->get_zonegroup().zones.size() > 1) {
7c673cae
FG
488 derr << "Placing Swift API in the root of URL hierarchy while running"
489 << " multi-site configuration requires another instance of RadosGW"
490 << " with S3 API enabled!" << dendl;
491 }
492
493 rest.register_default_mgr(set_logging(swift_resource));
494 }
495 }
496
497 if (apis_map.count("swift_auth") > 0) {
11fdf7f2 498 rest.register_resource(g_conf()->rgw_swift_auth_entry,
7c673cae
FG
499 set_logging(new RGWRESTMgr_SWIFT_Auth));
500 }
501
502 if (apis_map.count("admin") > 0) {
503 RGWRESTMgr_Admin *admin_resource = new RGWRESTMgr_Admin;
20effc67 504 admin_resource->register_resource("info", new RGWRESTMgr_Info);
7c673cae
FG
505 admin_resource->register_resource("usage", new RGWRESTMgr_Usage);
506 admin_resource->register_resource("user", new RGWRESTMgr_User);
20effc67 507 /* XXX dang part of this is RADOS specific */
7c673cae
FG
508 admin_resource->register_resource("bucket", new RGWRESTMgr_Bucket);
509
510 /*Registering resource for /admin/metadata */
511 admin_resource->register_resource("metadata", new RGWRESTMgr_Metadata);
20effc67 512 /* XXX dang ifdef these RADOS ? */
7c673cae 513 admin_resource->register_resource("log", new RGWRESTMgr_Log);
7c673cae
FG
514 admin_resource->register_resource("config", new RGWRESTMgr_Config);
515 admin_resource->register_resource("realm", new RGWRESTMgr_Realm);
20effc67 516 admin_resource->register_resource("ratelimit", new RGWRESTMgr_Ratelimit);
11fdf7f2 517 rest.register_resource(g_conf()->rgw_admin_entry, admin_resource);
7c673cae
FG
518 }
519
520 /* Initialize the registry of auth strategies which will coordinate
521 * the dynamic reconfiguration. */
9f95a23c
TL
522 rgw::auth::ImplicitTenants implicit_tenant_context{g_conf()};
523 g_conf().add_observer(&implicit_tenant_context);
7c673cae 524 auto auth_registry = \
20effc67 525 rgw::auth::StrategyRegistry::create(g_ceph_context, implicit_tenant_context, store);
7c673cae
FG
526
527 /* Header custom behavior */
11fdf7f2
TL
528 rest.register_x_headers(g_conf()->rgw_log_http_headers);
529
530 if (cct->_conf.get_val<std::string>("rgw_scheduler_type") == "dmclock" &&
531 !cct->check_experimental_feature_enabled("dmclock")){
532 derr << "dmclock scheduler type is experimental and needs to be"
533 << "set in the option enable experimental data corrupting features"
534 << dendl;
535 return EINVAL;
536 }
537
538 rgw::dmclock::SchedulerCtx sched_ctx{cct.get()};
7c673cae 539
a4b75251 540 OpsLogManifold *olog = new OpsLogManifold();
20effc67
TL
541 ActiveRateLimiter ratelimiting{cct.get()};
542 ratelimiting.start();
543
11fdf7f2 544 if (!g_conf()->rgw_ops_log_socket_path.empty()) {
a4b75251
TL
545 OpsLogSocket* olog_socket = new OpsLogSocket(g_ceph_context, g_conf()->rgw_ops_log_data_backlog);
546 olog_socket->init(g_conf()->rgw_ops_log_socket_path);
547 olog->add_sink(olog_socket);
548 }
549 OpsLogFile* ops_log_file;
550 if (!g_conf()->rgw_ops_log_file_path.empty()) {
551 ops_log_file = new OpsLogFile(g_ceph_context, g_conf()->rgw_ops_log_file_path, g_conf()->rgw_ops_log_data_backlog);
552 ops_log_file->start();
553 olog->add_sink(ops_log_file);
7c673cae 554 }
20effc67 555 olog->add_sink(new OpsLogRados(store));
7c673cae
FG
556
557 r = signal_fd_init();
558 if (r < 0) {
559 derr << "ERROR: unable to initialize signal fds" << dendl;
560 exit(1);
561 }
562
7c673cae
FG
563 register_async_signal_handler(SIGTERM, handle_sigterm);
564 register_async_signal_handler(SIGINT, handle_sigterm);
565 register_async_signal_handler(SIGUSR1, handle_sigterm);
566 sighandler_alrm = signal(SIGALRM, godown_alarm);
567
224ce89b
WB
568 map<string, string> service_map_meta;
569 service_map_meta["pid"] = stringify(getpid());
570
7c673cae
FG
571 list<RGWFrontend *> fes;
572
9f95a23c
TL
573 string frontend_defs_str = g_conf().get_val<string>("rgw_frontend_defaults");
574
575 list<string> frontends_def;
576 get_str_list(frontend_defs_str, ",", frontends_def);
577
578 map<string, std::unique_ptr<RGWFrontendConfig> > fe_def_map;
579 for (auto& f : frontends_def) {
580 RGWFrontendConfig *config = new RGWFrontendConfig(f);
581 int r = config->init();
582 if (r < 0) {
583 delete config;
584 cerr << "ERROR: failed to init default config: " << f << std::endl;
585 return EINVAL;
586 }
587
588 fe_def_map[config->get_framework()].reset(config);
589 }
590
224ce89b
WB
591 int fe_count = 0;
592
7c673cae 593 for (multimap<string, RGWFrontendConfig *>::iterator fiter = fe_map.begin();
224ce89b 594 fiter != fe_map.end(); ++fiter, ++fe_count) {
7c673cae
FG
595 RGWFrontendConfig *config = fiter->second;
596 string framework = config->get_framework();
9f95a23c
TL
597
598 auto def_iter = fe_def_map.find(framework);
599 if (def_iter != fe_def_map.end()) {
600 config->set_default_config(*def_iter->second);
601 }
602
7c673cae
FG
603 RGWFrontend *fe = NULL;
604
20effc67 605 if (framework == "loadgen") {
7c673cae
FG
606 int port;
607 config->get_val("port", 80, &port);
608 std::string uri_prefix;
609 config->get_val("prefix", "", &uri_prefix);
610
20effc67 611 RGWProcessEnv env = { store, &rest, olog, port, uri_prefix, auth_registry, &ratelimiting };
7c673cae
FG
612
613 fe = new RGWLoadGenFrontend(env, config);
614 }
11fdf7f2 615 else if (framework == "beast") {
7c673cae
FG
616 int port;
617 config->get_val("port", 80, &port);
618 std::string uri_prefix;
619 config->get_val("prefix", "", &uri_prefix);
20effc67 620 RGWProcessEnv env{ store, &rest, olog, port, uri_prefix, auth_registry, &ratelimiting };
11fdf7f2 621 fe = new RGWAsioFrontend(env, config, sched_ctx);
7c673cae 622 }
7c673cae 623
224ce89b
WB
624 service_map_meta["frontend_type#" + stringify(fe_count)] = framework;
625 service_map_meta["frontend_config#" + stringify(fe_count)] = config->get_config();
626
7c673cae
FG
627 if (fe == NULL) {
628 dout(0) << "WARNING: skipping unknown framework: " << framework << dendl;
629 continue;
630 }
631
632 dout(0) << "starting handler: " << fiter->first << dendl;
633 int r = fe->init();
634 if (r < 0) {
635 derr << "ERROR: failed initializing frontend" << dendl;
636 return -r;
637 }
638 r = fe->run();
639 if (r < 0) {
640 derr << "ERROR: failed run" << dendl;
641 return -r;
642 }
643
644 fes.push_back(fe);
645 }
646
20effc67 647 r = store->register_to_service_map(&dp, "rgw", service_map_meta);
224ce89b
WB
648 if (r < 0) {
649 derr << "ERROR: failed to register to service map: " << cpp_strerror(-r) << dendl;
650
651 /* ignore error */
652 }
653
654
7c673cae 655 // add a watcher to respond to realm configuration changes
b3b6e05e 656 RGWPeriodPusher pusher(&dp, store, null_yield);
9f95a23c 657 RGWFrontendPauser pauser(fes, implicit_tenant_context, &pusher);
f6b5b4d7
TL
658 auto reloader = std::make_unique<RGWRealmReloader>(store,
659 service_map_meta, &pauser);
7c673cae 660
20effc67 661 RGWRealmWatcher realm_watcher(&dp, g_ceph_context, store->get_zone()->get_realm());
f6b5b4d7 662 realm_watcher.add_watcher(RGWRealmNotify::Reload, *reloader);
7c673cae
FG
663 realm_watcher.add_watcher(RGWRealmNotify::ZonesNeedPeriod, pusher);
664
665#if defined(HAVE_SYS_PRCTL_H)
666 if (prctl(PR_SET_DUMPABLE, 1) == -1) {
667 cerr << "warning: unable to set dumpable flag: " << cpp_strerror(errno) << std::endl;
668 }
669#endif
670
671 wait_shutdown();
672
673 derr << "shutting down" << dendl;
674
f6b5b4d7
TL
675 reloader.reset(); // stop the realm reloader
676
7c673cae
FG
677 for (list<RGWFrontend *>::iterator liter = fes.begin(); liter != fes.end();
678 ++liter) {
679 RGWFrontend *fe = *liter;
680 fe->stop();
681 }
682
683 for (list<RGWFrontend *>::iterator liter = fes.begin(); liter != fes.end();
684 ++liter) {
685 RGWFrontend *fe = *liter;
686 fe->join();
687 delete fe;
688 }
689
690 for (list<RGWFrontendConfig *>::iterator liter = configs.begin();
691 liter != configs.end(); ++liter) {
692 RGWFrontendConfig *fec = *liter;
693 delete fec;
694 }
695
b32b8144 696 unregister_async_signal_handler(SIGHUP, sighup_handler);
7c673cae
FG
697 unregister_async_signal_handler(SIGTERM, handle_sigterm);
698 unregister_async_signal_handler(SIGINT, handle_sigterm);
699 unregister_async_signal_handler(SIGUSR1, handle_sigterm);
700 shutdown_async_signal_handler();
701
702 rgw_log_usage_finalize();
7c673cae
FG
703 delete olog;
704
20effc67 705 StoreManager::close_storage(store);
11fdf7f2 706 rgw::auth::s3::LDAPEngine::shutdown();
7c673cae
FG
707 rgw_tools_cleanup();
708 rgw_shutdown_resolver();
11fdf7f2 709 rgw_http_client_cleanup();
f67539c2 710 rgw_kmip_client_cleanup();
94b18763 711 rgw::curl::cleanup_curl();
9f95a23c 712 g_conf().remove_observer(&implicit_tenant_context);
eafe8130
TL
713#ifdef WITH_RADOSGW_AMQP_ENDPOINT
714 rgw::amqp::shutdown();
715#endif
9f95a23c
TL
716#ifdef WITH_RADOSGW_KAFKA_ENDPOINT
717 rgw::kafka::shutdown();
718#endif
7c673cae
FG
719
720 rgw_perf_stop(g_ceph_context);
721
722 dout(1) << "final shutdown" << dendl;
723
724 signal_fd_finalize();
725
726 return 0;
727}
9f95a23c
TL
728
729extern "C" {
730
731int radosgw_main(int argc, const char** argv)
732{
733 return radosgw_Main(argc, argv);
734}
735
736} /* extern "C" */
737