]> git.proxmox.com Git - ceph.git/blame - ceph/src/mgr/MgrStandby.cc
update sources to v12.1.1
[ceph.git] / ceph / src / mgr / MgrStandby.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2016 John Spray <john.spray@redhat.com>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 */
13
14#include <Python.h>
15
16#include "common/errno.h"
31f18b77
FG
17#include "common/signal.h"
18#include "include/compat.h"
7c673cae
FG
19
20#include "include/stringify.h"
21#include "global/global_context.h"
22#include "global/signal_handler.h"
23
24#include "mgr/MgrContext.h"
25
26#include "messages/MMgrBeacon.h"
27#include "messages/MMgrMap.h"
28#include "Mgr.h"
29
30#include "MgrStandby.h"
31
32#define dout_context g_ceph_context
33#define dout_subsys ceph_subsys_mgr
34#undef dout_prefix
35#define dout_prefix *_dout << "mgr " << __func__ << " "
36
37
31f18b77 38MgrStandby::MgrStandby(int argc, const char **argv) :
7c673cae
FG
39 Dispatcher(g_ceph_context),
40 monc{g_ceph_context},
41 client_messenger(Messenger::create_client_messenger(g_ceph_context, "mgr")),
42 objecter{g_ceph_context, client_messenger.get(), &monc, NULL, 0, 0},
43 client{client_messenger.get(), &monc, &objecter},
44 log_client(g_ceph_context, client_messenger.get(), &monc.monmap, LogClient::NO_FLAGS),
45 clog(log_client.create_channel(CLOG_CHANNEL_CLUSTER)),
46 audit_clog(log_client.create_channel(CLOG_CHANNEL_AUDIT)),
47 lock("MgrStandby::lock"),
48 timer(g_ceph_context, lock),
31f18b77
FG
49 active_mgr(nullptr),
50 orig_argc(argc),
51 orig_argv(argv)
7c673cae
FG
52{
53}
54
55MgrStandby::~MgrStandby() = default;
56
57const char** MgrStandby::get_tracked_conf_keys() const
58{
59 static const char* KEYS[] = {
60 // clog & admin clog
61 "clog_to_monitors",
62 "clog_to_syslog",
63 "clog_to_syslog_facility",
64 "clog_to_syslog_level",
65 "osd_objectstore_fuse",
66 "clog_to_graylog",
67 "clog_to_graylog_host",
68 "clog_to_graylog_port",
69 "host",
70 "fsid",
71 NULL
72 };
73 return KEYS;
74}
75
76void MgrStandby::handle_conf_change(
77 const struct md_config_t *conf,
78 const std::set <std::string> &changed)
79{
80 if (changed.count("clog_to_monitors") ||
81 changed.count("clog_to_syslog") ||
82 changed.count("clog_to_syslog_level") ||
83 changed.count("clog_to_syslog_facility") ||
84 changed.count("clog_to_graylog") ||
85 changed.count("clog_to_graylog_host") ||
86 changed.count("clog_to_graylog_port") ||
87 changed.count("host") ||
88 changed.count("fsid")) {
89 _update_log_config();
90 }
91}
92
93int MgrStandby::init()
94{
95 Mutex::Locker l(lock);
96
97 // Initialize Messenger
98 client_messenger->add_dispatcher_tail(this);
99 client_messenger->add_dispatcher_head(&objecter);
100 client_messenger->add_dispatcher_tail(&client);
101 client_messenger->start();
102
103 // Initialize MonClient
104 if (monc.build_initial_monmap() < 0) {
105 client_messenger->shutdown();
106 client_messenger->wait();
107 return -1;
108 }
109
110 monc.sub_want("mgrmap", 0, 0);
111
112 monc.set_want_keys(CEPH_ENTITY_TYPE_MON|CEPH_ENTITY_TYPE_OSD
113 |CEPH_ENTITY_TYPE_MDS|CEPH_ENTITY_TYPE_MGR);
114 monc.set_messenger(client_messenger.get());
115 int r = monc.init();
116 if (r < 0) {
117 monc.shutdown();
118 client_messenger->shutdown();
119 client_messenger->wait();
120 return r;
121 }
122 r = monc.authenticate();
123 if (r < 0) {
124 derr << "Authentication failed, did you specify a mgr ID with a valid keyring?" << dendl;
125 monc.shutdown();
126 client_messenger->shutdown();
127 client_messenger->wait();
128 return r;
129 }
130
131 client_t whoami = monc.get_global_id();
132 client_messenger->set_myname(entity_name_t::CLIENT(whoami.v));
133 monc.set_log_client(&log_client);
134 _update_log_config();
135 objecter.set_client_incarnation(0);
136 objecter.init();
137 objecter.start();
138 client.init();
139 timer.init();
140
31f18b77 141 tick();
7c673cae
FG
142
143 dout(4) << "Complete." << dendl;
144 return 0;
145}
146
147void MgrStandby::send_beacon()
148{
149 assert(lock.is_locked_by_me());
150 dout(1) << state_str() << dendl;
7c673cae 151
224ce89b
WB
152 set<string> modules;
153 PyModules::list_modules(&modules);
7c673cae
FG
154 bool available = active_mgr != nullptr && active_mgr->is_initialized();
155 auto addr = available ? active_mgr->get_server_addr() : entity_addr_t();
224ce89b
WB
156 dout(10) << "sending beacon as gid " << monc.get_global_id()
157 << " modules " << modules << dendl;
158
7c673cae
FG
159 MMgrBeacon *m = new MMgrBeacon(monc.get_fsid(),
160 monc.get_global_id(),
161 g_conf->name.get_id(),
162 addr,
224ce89b
WB
163 available,
164 modules);
7c673cae 165 monc.send_mon_message(m);
31f18b77
FG
166}
167
168void MgrStandby::tick()
169{
224ce89b 170 dout(10) << __func__ << dendl;
31f18b77
FG
171 send_beacon();
172
173 if (active_mgr) {
174 active_mgr->tick();
175 }
176
177 timer.add_event_after(g_conf->mgr_tick_period, new FunctionContext(
7c673cae 178 [this](int r){
31f18b77 179 tick();
7c673cae
FG
180 }
181 ));
182}
183
184void MgrStandby::handle_signal(int signum)
185{
186 Mutex::Locker l(lock);
187 assert(signum == SIGINT || signum == SIGTERM);
188 derr << "*** Got signal " << sig_str(signum) << " ***" << dendl;
189 shutdown();
190}
191
192void MgrStandby::shutdown()
193{
194 // Expect already to be locked as we're called from signal handler
195 assert(lock.is_locked_by_me());
196
197 // stop sending beacon first, i use monc to talk with monitors
198 timer.shutdown();
199 // client uses monc and objecter
200 client.shutdown();
201 // stop monc, so mon won't be able to instruct me to shutdown/activate after
202 // the active_mgr is stopped
203 monc.shutdown();
204 if (active_mgr) {
205 active_mgr->shutdown();
206 }
207 // objecter is used by monc and active_mgr
208 objecter.shutdown();
209 // client_messenger is used by all of them, so stop it in the end
210 client_messenger->shutdown();
211}
212
31f18b77
FG
213void MgrStandby::respawn()
214{
215 char *new_argv[orig_argc+1];
216 dout(1) << " e: '" << orig_argv[0] << "'" << dendl;
217 for (int i=0; i<orig_argc; i++) {
218 new_argv[i] = (char *)orig_argv[i];
219 dout(1) << " " << i << ": '" << orig_argv[i] << "'" << dendl;
220 }
221 new_argv[orig_argc] = NULL;
222
223 /* Determine the path to our executable, test if Linux /proc/self/exe exists.
224 * This allows us to exec the same executable even if it has since been
225 * unlinked.
226 */
227 char exe_path[PATH_MAX] = "";
228 if (readlink(PROCPREFIX "/proc/self/exe", exe_path, PATH_MAX-1) == -1) {
229 /* Print CWD for the user's interest */
230 char buf[PATH_MAX];
231 char *cwd = getcwd(buf, sizeof(buf));
232 assert(cwd);
233 dout(1) << " cwd " << cwd << dendl;
234
235 /* Fall back to a best-effort: just running in our CWD */
236 strncpy(exe_path, orig_argv[0], PATH_MAX-1);
237 } else {
238 dout(1) << "respawning with exe " << exe_path << dendl;
239 strcpy(exe_path, PROCPREFIX "/proc/self/exe");
240 }
241
242 dout(1) << " exe_path " << exe_path << dendl;
243
244 unblock_all_signals(NULL);
245 execv(exe_path, new_argv);
246
247 derr << "respawn execv " << orig_argv[0]
248 << " failed with " << cpp_strerror(errno) << dendl;
249 ceph_abort();
250}
251
7c673cae
FG
252void MgrStandby::_update_log_config()
253{
254 map<string,string> log_to_monitors;
255 map<string,string> log_to_syslog;
256 map<string,string> log_channel;
257 map<string,string> log_prio;
258 map<string,string> log_to_graylog;
259 map<string,string> log_to_graylog_host;
260 map<string,string> log_to_graylog_port;
261 uuid_d fsid;
262 string host;
263
264 if (parse_log_client_options(cct, log_to_monitors, log_to_syslog,
265 log_channel, log_prio, log_to_graylog,
266 log_to_graylog_host, log_to_graylog_port,
267 fsid, host) == 0) {
268 clog->update_config(log_to_monitors, log_to_syslog,
269 log_channel, log_prio, log_to_graylog,
270 log_to_graylog_host, log_to_graylog_port,
271 fsid, host);
272 audit_clog->update_config(log_to_monitors, log_to_syslog,
273 log_channel, log_prio, log_to_graylog,
274 log_to_graylog_host, log_to_graylog_port,
275 fsid, host);
276 }
277}
278
279void MgrStandby::handle_mgr_map(MMgrMap* mmap)
280{
281 auto map = mmap->get_map();
282 dout(4) << "received map epoch " << map.get_epoch() << dendl;
283 const bool active_in_map = map.active_gid == monc.get_global_id();
284 dout(4) << "active in map: " << active_in_map
285 << " active is " << map.active_gid << dendl;
286 if (active_in_map) {
287 if (!active_mgr) {
288 dout(1) << "Activating!" << dendl;
224ce89b 289 active_mgr.reset(new Mgr(&monc, map, client_messenger.get(), &objecter,
7c673cae 290 &client, clog, audit_clog));
224ce89b
WB
291 active_mgr->background_init(new FunctionContext(
292 [this](int r){
293 // Advertise our active-ness ASAP instead of waiting for
294 // next tick.
295 Mutex::Locker l(lock);
296 send_beacon();
297 }));
298 dout(1) << "I am now activating" << dendl;
7c673cae
FG
299 } else {
300 dout(10) << "I was already active" << dendl;
224ce89b
WB
301 bool need_respawn = active_mgr->got_mgr_map(map);
302 if (need_respawn) {
303 respawn();
304 }
7c673cae
FG
305 }
306 } else {
307 if (active_mgr != nullptr) {
308 derr << "I was active but no longer am" << dendl;
31f18b77 309 respawn();
7c673cae
FG
310 }
311 }
312
313 mmap->put();
314}
315
316bool MgrStandby::ms_dispatch(Message *m)
317{
318 Mutex::Locker l(lock);
319 dout(4) << state_str() << " " << *m << dendl;
320
31f18b77
FG
321 if (m->get_type() == MSG_MGR_MAP) {
322 handle_mgr_map(static_cast<MMgrMap*>(m));
323 return true;
324 } else if (active_mgr) {
325 auto am = active_mgr;
326 lock.Unlock();
327 bool handled = am->ms_dispatch(m);
328 lock.Lock();
329 return handled;
330 } else {
331 return false;
7c673cae 332 }
7c673cae
FG
333}
334
335
336bool MgrStandby::ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer,
337 bool force_new)
338{
339 if (dest_type == CEPH_ENTITY_TYPE_MON)
340 return true;
341
342 if (force_new) {
343 if (monc.wait_auth_rotating(10) < 0)
344 return false;
345 }
346
347 *authorizer = monc.build_authorizer(dest_type);
348 return *authorizer != NULL;
349}
350
351bool MgrStandby::ms_handle_refused(Connection *con)
352{
353 // do nothing for now
354 return false;
355}
356
357// A reference for use by the signal handler
358static MgrStandby *signal_mgr = nullptr;
359
360static void handle_mgr_signal(int signum)
361{
362 if (signal_mgr) {
363 signal_mgr->handle_signal(signum);
364 }
365}
366
367int MgrStandby::main(vector<const char *> args)
368{
369 // Enable signal handlers
370 signal_mgr = this;
371 init_async_signal_handler();
372 register_async_signal_handler(SIGHUP, sighup_handler);
373 register_async_signal_handler_oneshot(SIGINT, handle_mgr_signal);
374 register_async_signal_handler_oneshot(SIGTERM, handle_mgr_signal);
375
376 client_messenger->wait();
377
378 // Disable signal handlers
379 unregister_async_signal_handler(SIGHUP, sighup_handler);
380 unregister_async_signal_handler(SIGINT, handle_mgr_signal);
381 unregister_async_signal_handler(SIGTERM, handle_mgr_signal);
382 shutdown_async_signal_handler();
383 signal_mgr = nullptr;
384
385 return 0;
386}
387
388
389std::string MgrStandby::state_str()
390{
391 return active_mgr == nullptr ? "standby" : "active";
392}
393