1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "include/compat.h"
5 #include "CrushLocation.h"
6 #include "CrushWrapper.h"
7 #include "common/ceph_context.h"
8 #include "common/config.h"
9 #include "include/str_list.h"
10 #include "common/debug.h"
11 #include "common/errno.h"
12 #include "include/common_fwd.h"
13 #include "include/compat.h"
15 #include "common/SubProcess.h"
19 namespace TOPNSPC::crush
{
21 int CrushLocation::update_from_conf()
23 if (cct
->_conf
->crush_location
.length())
24 return _parse(cct
->_conf
->crush_location
);
28 int CrushLocation::_parse(const std::string
& s
)
30 std::multimap
<std::string
,std::string
> new_crush_location
;
31 std::vector
<std::string
> lvec
;
32 get_str_vec(s
, ";, \t", lvec
);
33 int r
= CrushWrapper::parse_loc_multimap(lvec
, &new_crush_location
);
35 lderr(cct
) << "warning: crush_location '" << cct
->_conf
->crush_location
36 << "' does not parse, keeping original crush_location "
40 std::lock_guard
l(lock
);
41 loc
.swap(new_crush_location
);
42 lgeneric_dout(cct
, 10) << "crush_location is " << loc
<< dendl
;
46 int CrushLocation::update_from_hook()
48 if (cct
->_conf
->crush_location_hook
.length() == 0)
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);
100 int CrushLocation::init_on_startup()
102 if (cct
->_conf
->crush_location
.length()) {
103 return update_from_conf();
105 if (cct
->_conf
->crush_location_hook
.length()) {
106 return update_from_hook();
109 // start with a sane default
110 char hostname
[HOST_NAME_MAX
+ 1];
111 int r
= gethostname(hostname
, sizeof(hostname
));
113 strcpy(hostname
, "unknown_host");
114 // use short hostname
115 for (unsigned i
=0; hostname
[i
]; ++i
) {
116 if (hostname
[i
] == '.') {
121 std::lock_guard
l(lock
);
123 loc
.insert(std::make_pair
<std::string
,std::string
>("host", hostname
));
124 loc
.insert(std::make_pair
<std::string
,std::string
>("root", "default"));
125 lgeneric_dout(cct
, 10) << "crush_location is (default) " << loc
<< dendl
;
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
<< '"';