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