]>
git.proxmox.com Git - ceph.git/blob - ceph/src/mgr/MgrStandby.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2016 John Spray <john.spray@redhat.com>
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.
16 #include "common/errno.h"
17 #include "common/signal.h"
18 #include "include/compat.h"
20 #include "include/stringify.h"
21 #include "global/global_context.h"
22 #include "global/signal_handler.h"
24 #include "mgr/MgrContext.h"
26 #include "messages/MMgrBeacon.h"
27 #include "messages/MMgrMap.h"
30 #include "MgrStandby.h"
32 #define dout_context g_ceph_context
33 #define dout_subsys ceph_subsys_mgr
35 #define dout_prefix *_dout << "mgr " << __func__ << " "
38 MgrStandby::MgrStandby(int argc
, const char **argv
) :
39 Dispatcher(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
),
55 MgrStandby::~MgrStandby() = default;
57 const char** MgrStandby::get_tracked_conf_keys() const
59 static const char* KEYS
[] = {
63 "clog_to_syslog_facility",
64 "clog_to_syslog_level",
65 "osd_objectstore_fuse",
67 "clog_to_graylog_host",
68 "clog_to_graylog_port",
76 void MgrStandby::handle_conf_change(
77 const struct md_config_t
*conf
,
78 const std::set
<std::string
> &changed
)
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")) {
93 int MgrStandby::init()
95 Mutex::Locker
l(lock
);
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();
103 // Initialize MonClient
104 if (monc
.build_initial_monmap() < 0) {
105 client_messenger
->shutdown();
106 client_messenger
->wait();
110 monc
.sub_want("mgrmap", 0, 0);
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());
118 client_messenger
->shutdown();
119 client_messenger
->wait();
122 r
= monc
.authenticate();
124 derr
<< "Authentication failed, did you specify a mgr ID with a valid keyring?" << dendl
;
126 client_messenger
->shutdown();
127 client_messenger
->wait();
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);
143 dout(4) << "Complete." << dendl
;
147 void MgrStandby::send_beacon()
149 assert(lock
.is_locked_by_me());
150 dout(1) << state_str() << dendl
;
153 PyModules::list_modules(&modules
);
154 bool available
= active_mgr
!= nullptr && active_mgr
->is_initialized();
155 auto addr
= available
? active_mgr
->get_server_addr() : entity_addr_t();
156 dout(10) << "sending beacon as gid " << monc
.get_global_id()
157 << " modules " << modules
<< dendl
;
159 MMgrBeacon
*m
= new MMgrBeacon(monc
.get_fsid(),
160 monc
.get_global_id(),
161 g_conf
->name
.get_id(),
165 monc
.send_mon_message(m
);
168 void MgrStandby::tick()
170 dout(10) << __func__
<< dendl
;
177 timer
.add_event_after(g_conf
->mgr_tick_period
, new FunctionContext(
184 void MgrStandby::handle_signal(int signum
)
186 Mutex::Locker
l(lock
);
187 assert(signum
== SIGINT
|| signum
== SIGTERM
);
188 derr
<< "*** Got signal " << sig_str(signum
) << " ***" << dendl
;
192 void MgrStandby::shutdown()
194 // Expect already to be locked as we're called from signal handler
195 assert(lock
.is_locked_by_me());
197 // stop sending beacon first, i use monc to talk with monitors
199 // client uses monc and objecter
201 // stop monc, so mon won't be able to instruct me to shutdown/activate after
202 // the active_mgr is stopped
205 active_mgr
->shutdown();
207 // objecter is used by monc and active_mgr
209 // client_messenger is used by all of them, so stop it in the end
210 client_messenger
->shutdown();
213 void MgrStandby::respawn()
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
;
221 new_argv
[orig_argc
] = NULL
;
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
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 */
231 char *cwd
= getcwd(buf
, sizeof(buf
));
233 dout(1) << " cwd " << cwd
<< dendl
;
235 /* Fall back to a best-effort: just running in our CWD */
236 strncpy(exe_path
, orig_argv
[0], PATH_MAX
-1);
238 dout(1) << "respawning with exe " << exe_path
<< dendl
;
239 strcpy(exe_path
, PROCPREFIX
"/proc/self/exe");
242 dout(1) << " exe_path " << exe_path
<< dendl
;
244 unblock_all_signals(NULL
);
245 execv(exe_path
, new_argv
);
247 derr
<< "respawn execv " << orig_argv
[0]
248 << " failed with " << cpp_strerror(errno
) << dendl
;
252 void MgrStandby::_update_log_config()
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
;
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
,
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
,
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
,
279 void MgrStandby::handle_mgr_map(MMgrMap
* mmap
)
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
;
288 dout(1) << "Activating!" << dendl
;
289 active_mgr
.reset(new Mgr(&monc
, map
, client_messenger
.get(), &objecter
,
290 &client
, clog
, audit_clog
));
291 active_mgr
->background_init(new FunctionContext(
293 // Advertise our active-ness ASAP instead of waiting for
295 Mutex::Locker
l(lock
);
298 dout(1) << "I am now activating" << dendl
;
300 dout(10) << "I was already active" << dendl
;
301 bool need_respawn
= active_mgr
->got_mgr_map(map
);
307 if (active_mgr
!= nullptr) {
308 derr
<< "I was active but no longer am" << dendl
;
316 bool MgrStandby::ms_dispatch(Message
*m
)
318 Mutex::Locker
l(lock
);
319 dout(4) << state_str() << " " << *m
<< dendl
;
321 if (m
->get_type() == MSG_MGR_MAP
) {
322 handle_mgr_map(static_cast<MMgrMap
*>(m
));
324 } else if (active_mgr
) {
325 auto am
= active_mgr
;
327 bool handled
= am
->ms_dispatch(m
);
336 bool MgrStandby::ms_get_authorizer(int dest_type
, AuthAuthorizer
**authorizer
,
339 if (dest_type
== CEPH_ENTITY_TYPE_MON
)
343 if (monc
.wait_auth_rotating(10) < 0)
347 *authorizer
= monc
.build_authorizer(dest_type
);
348 return *authorizer
!= NULL
;
351 bool MgrStandby::ms_handle_refused(Connection
*con
)
353 // do nothing for now
357 // A reference for use by the signal handler
358 static MgrStandby
*signal_mgr
= nullptr;
360 static void handle_mgr_signal(int signum
)
363 signal_mgr
->handle_signal(signum
);
367 int MgrStandby::main(vector
<const char *> args
)
369 // Enable signal handlers
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
);
376 client_messenger
->wait();
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;
389 std::string
MgrStandby::state_str()
391 return active_mgr
== nullptr ? "standby" : "active";