1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
6 #include "CrushLocation.h"
7 #include "CrushWrapper.h"
8 #include "common/ceph_context.h"
9 #include "common/config.h"
10 #include "common/debug.h"
11 #include "common/errno.h"
12 #include "include/common_fwd.h"
13 #include "include/compat.h"
14 #include "include/str_list.h"
16 namespace ceph::crush
{
18 int CrushLocation::update_from_conf()
20 if (cct
->_conf
->crush_location
.length())
21 return _parse(cct
->_conf
->crush_location
);
25 int CrushLocation::_parse(const std::string
& s
)
27 std::multimap
<std::string
,std::string
> new_crush_location
;
28 std::vector
<std::string
> lvec
;
29 get_str_vec(s
, ";, \t", lvec
);
30 int r
= CrushWrapper::parse_loc_multimap(lvec
, &new_crush_location
);
32 lderr(cct
) << "warning: crush_location '" << cct
->_conf
->crush_location
33 << "' does not parse, keeping original crush_location "
37 std::lock_guard
l(lock
);
38 loc
.swap(new_crush_location
);
39 lgeneric_dout(cct
, 10) << "crush_location is " << loc
<< dendl
;
43 int CrushLocation::update_from_hook()
45 if (cct
->_conf
->crush_location_hook
.length() == 0)
48 #if defined(WITH_SEASTAR) && !defined(WITH_ALIEN)
49 ceph_abort_msg("crimson does not support crush_location_hook, it must stay empty");
51 if (0 != access(cct
->_conf
->crush_location_hook
.c_str(), R_OK
)) {
52 lderr(cct
) << "the user define crush location hook: " << cct
->_conf
->crush_location_hook
53 << " may not exist or can not access it" << dendl
;
58 cct
->_conf
->crush_location_hook
.c_str(),
59 SubProcess::CLOSE
, SubProcess::PIPE
, SubProcess::PIPE
,
60 cct
->_conf
->crush_location_hook_timeout
);
62 "--cluster", cct
->_conf
->cluster
.c_str(),
63 "--id", cct
->_conf
->name
.get_id().c_str(),
64 "--type", cct
->_conf
->name
.get_type_str(),
66 int ret
= hook
.spawn();
68 lderr(cct
) << "error: failed run " << cct
->_conf
->crush_location_hook
<< ": "
69 << hook
.err() << dendl
;
73 ceph::buffer::list bl
;
74 ret
= bl
.read_fd(hook
.get_stdout(), 100 * 1024);
76 lderr(cct
) << "error: failed read stdout from "
77 << cct
->_conf
->crush_location_hook
78 << ": " << cpp_strerror(-ret
) << dendl
;
79 ceph::buffer::list err
;
80 err
.read_fd(hook
.get_stderr(), 100 * 1024);
81 lderr(cct
) << "stderr:\n";
86 if (hook
.join() != 0) {
87 lderr(cct
) << "error: failed to join: " << hook
.err() << dendl
;
95 bl
.begin().copy(bl
.length(), out
);
96 out
.erase(out
.find_last_not_of(" \n\r\t")+1);
98 #endif // WITH_SEASTAR && !WITH_ALIEN
101 int CrushLocation::init_on_startup()
103 if (cct
->_conf
->crush_location
.length()) {
104 return update_from_conf();
106 if (cct
->_conf
->crush_location_hook
.length()) {
107 return update_from_hook();
110 // start with a sane default
111 char hostname
[HOST_NAME_MAX
+ 1];
112 int r
= gethostname(hostname
, sizeof(hostname
));
114 strcpy(hostname
, "unknown_host");
115 // use short hostname
116 for (unsigned i
=0; hostname
[i
]; ++i
) {
117 if (hostname
[i
] == '.') {
122 std::lock_guard
l(lock
);
124 loc
.insert(std::make_pair
<std::string
,std::string
>("host", hostname
));
125 loc
.insert(std::make_pair
<std::string
,std::string
>("root", "default"));
129 std::multimap
<std::string
,std::string
> CrushLocation::get_location() const
131 std::lock_guard
l(lock
);
135 std::ostream
& operator<<(std::ostream
& os
, const CrushLocation
& loc
)
138 for (auto& [type
, pos
] : loc
.get_location()) {
144 os
<< '"' << type
<< '=' << pos
<< '"';