]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
20effc67 | 4 | #include <vector> |
f51cf556 | 5 | #include <boost/algorithm/string/trim.hpp> |
20effc67 | 6 | |
7c673cae FG |
7 | #include "CrushLocation.h" |
8 | #include "CrushWrapper.h" | |
11fdf7f2 | 9 | #include "common/ceph_context.h" |
7c673cae | 10 | #include "common/config.h" |
7c673cae | 11 | #include "common/debug.h" |
11fdf7f2 | 12 | #include "common/errno.h" |
9f95a23c | 13 | #include "include/common_fwd.h" |
7c673cae | 14 | #include "include/compat.h" |
20effc67 | 15 | #include "include/str_list.h" |
7c673cae | 16 | |
1e59de90 | 17 | namespace ceph::crush { |
9f95a23c | 18 | |
7c673cae FG |
19 | int CrushLocation::update_from_conf() |
20 | { | |
21 | if (cct->_conf->crush_location.length()) | |
22 | return _parse(cct->_conf->crush_location); | |
23 | return 0; | |
24 | } | |
25 | ||
26 | int CrushLocation::_parse(const std::string& s) | |
27 | { | |
28 | std::multimap<std::string,std::string> new_crush_location; | |
29 | std::vector<std::string> lvec; | |
30 | get_str_vec(s, ";, \t", lvec); | |
31 | int r = CrushWrapper::parse_loc_multimap(lvec, &new_crush_location); | |
32 | if (r < 0) { | |
33 | lderr(cct) << "warning: crush_location '" << cct->_conf->crush_location | |
34 | << "' does not parse, keeping original crush_location " | |
35 | << loc << dendl; | |
36 | return -EINVAL; | |
37 | } | |
9f95a23c | 38 | std::lock_guard l(lock); |
7c673cae FG |
39 | loc.swap(new_crush_location); |
40 | lgeneric_dout(cct, 10) << "crush_location is " << loc << dendl; | |
41 | return 0; | |
42 | } | |
43 | ||
44 | int CrushLocation::update_from_hook() | |
45 | { | |
46 | if (cct->_conf->crush_location_hook.length() == 0) | |
47 | return 0; | |
48 | ||
49 | if (0 != access(cct->_conf->crush_location_hook.c_str(), R_OK)) { | |
50 | lderr(cct) << "the user define crush location hook: " << cct->_conf->crush_location_hook | |
51 | << " may not exist or can not access it" << dendl; | |
52 | return errno; | |
53 | } | |
54 | ||
55 | SubProcessTimed hook( | |
56 | cct->_conf->crush_location_hook.c_str(), | |
57 | SubProcess::CLOSE, SubProcess::PIPE, SubProcess::PIPE, | |
58 | cct->_conf->crush_location_hook_timeout); | |
59 | hook.add_cmd_args( | |
60 | "--cluster", cct->_conf->cluster.c_str(), | |
61 | "--id", cct->_conf->name.get_id().c_str(), | |
62 | "--type", cct->_conf->name.get_type_str(), | |
63 | NULL); | |
64 | int ret = hook.spawn(); | |
65 | if (ret != 0) { | |
66 | lderr(cct) << "error: failed run " << cct->_conf->crush_location_hook << ": " | |
67 | << hook.err() << dendl; | |
68 | return ret; | |
69 | } | |
70 | ||
9f95a23c | 71 | ceph::buffer::list bl; |
7c673cae FG |
72 | ret = bl.read_fd(hook.get_stdout(), 100 * 1024); |
73 | if (ret < 0) { | |
74 | lderr(cct) << "error: failed read stdout from " | |
75 | << cct->_conf->crush_location_hook | |
76 | << ": " << cpp_strerror(-ret) << dendl; | |
9f95a23c | 77 | ceph::buffer::list err; |
7c673cae FG |
78 | err.read_fd(hook.get_stderr(), 100 * 1024); |
79 | lderr(cct) << "stderr:\n"; | |
80 | err.hexdump(*_dout); | |
81 | *_dout << dendl; | |
7c673cae FG |
82 | } |
83 | ||
84 | if (hook.join() != 0) { | |
85 | lderr(cct) << "error: failed to join: " << hook.err() << dendl; | |
86 | return -EINVAL; | |
87 | } | |
88 | ||
11fdf7f2 TL |
89 | if (ret < 0) |
90 | return ret; | |
91 | ||
7c673cae | 92 | std::string out; |
9f95a23c | 93 | bl.begin().copy(bl.length(), out); |
f51cf556 | 94 | boost::algorithm::trim_right_if(out, boost::algorithm::is_any_of(" \n\r\t")); |
7c673cae FG |
95 | return _parse(out); |
96 | } | |
97 | ||
98 | int CrushLocation::init_on_startup() | |
99 | { | |
100 | if (cct->_conf->crush_location.length()) { | |
101 | return update_from_conf(); | |
102 | } | |
103 | if (cct->_conf->crush_location_hook.length()) { | |
104 | return update_from_hook(); | |
105 | } | |
106 | ||
107 | // start with a sane default | |
108 | char hostname[HOST_NAME_MAX + 1]; | |
92f5a8d4 | 109 | int r = gethostname(hostname, sizeof(hostname)); |
7c673cae FG |
110 | if (r < 0) |
111 | strcpy(hostname, "unknown_host"); | |
112 | // use short hostname | |
113 | for (unsigned i=0; hostname[i]; ++i) { | |
114 | if (hostname[i] == '.') { | |
115 | hostname[i] = '\0'; | |
116 | break; | |
117 | } | |
118 | } | |
9f95a23c | 119 | std::lock_guard l(lock); |
7c673cae | 120 | loc.clear(); |
9f95a23c TL |
121 | loc.insert(std::make_pair<std::string,std::string>("host", hostname)); |
122 | loc.insert(std::make_pair<std::string,std::string>("root", "default")); | |
7c673cae FG |
123 | return 0; |
124 | } | |
9f95a23c TL |
125 | |
126 | std::multimap<std::string,std::string> CrushLocation::get_location() const | |
127 | { | |
128 | std::lock_guard l(lock); | |
129 | return loc; | |
130 | } | |
131 | ||
132 | std::ostream& operator<<(std::ostream& os, const CrushLocation& loc) | |
133 | { | |
134 | bool first = true; | |
135 | for (auto& [type, pos] : loc.get_location()) { | |
136 | if (first) { | |
137 | first = false; | |
138 | } else { | |
139 | os << ", "; | |
140 | } | |
141 | os << '"' << type << '=' << pos << '"'; | |
142 | } | |
143 | return os; | |
144 | } | |
145 | ||
146 | } |