]> git.proxmox.com Git - ceph.git/blob - ceph/src/crush/CrushLocation.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / crush / CrushLocation.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include <vector>
5
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"
15
16 namespace ceph::crush {
17
18 int CrushLocation::update_from_conf()
19 {
20 if (cct->_conf->crush_location.length())
21 return _parse(cct->_conf->crush_location);
22 return 0;
23 }
24
25 int CrushLocation::_parse(const std::string& s)
26 {
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);
31 if (r < 0) {
32 lderr(cct) << "warning: crush_location '" << cct->_conf->crush_location
33 << "' does not parse, keeping original crush_location "
34 << loc << dendl;
35 return -EINVAL;
36 }
37 std::lock_guard l(lock);
38 loc.swap(new_crush_location);
39 lgeneric_dout(cct, 10) << "crush_location is " << loc << dendl;
40 return 0;
41 }
42
43 int CrushLocation::update_from_hook()
44 {
45 if (cct->_conf->crush_location_hook.length() == 0)
46 return 0;
47
48 #if defined(WITH_SEASTAR) && !defined(WITH_ALIEN)
49 ceph_abort_msg("crimson does not support crush_location_hook, it must stay empty");
50 #else
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;
54 return errno;
55 }
56
57 SubProcessTimed hook(
58 cct->_conf->crush_location_hook.c_str(),
59 SubProcess::CLOSE, SubProcess::PIPE, SubProcess::PIPE,
60 cct->_conf->crush_location_hook_timeout);
61 hook.add_cmd_args(
62 "--cluster", cct->_conf->cluster.c_str(),
63 "--id", cct->_conf->name.get_id().c_str(),
64 "--type", cct->_conf->name.get_type_str(),
65 NULL);
66 int ret = hook.spawn();
67 if (ret != 0) {
68 lderr(cct) << "error: failed run " << cct->_conf->crush_location_hook << ": "
69 << hook.err() << dendl;
70 return ret;
71 }
72
73 ceph::buffer::list bl;
74 ret = bl.read_fd(hook.get_stdout(), 100 * 1024);
75 if (ret < 0) {
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";
82 err.hexdump(*_dout);
83 *_dout << dendl;
84 }
85
86 if (hook.join() != 0) {
87 lderr(cct) << "error: failed to join: " << hook.err() << dendl;
88 return -EINVAL;
89 }
90
91 if (ret < 0)
92 return ret;
93
94 std::string out;
95 bl.begin().copy(bl.length(), out);
96 out.erase(out.find_last_not_of(" \n\r\t")+1);
97 return _parse(out);
98 #endif // WITH_SEASTAR && !WITH_ALIEN
99 }
100
101 int CrushLocation::init_on_startup()
102 {
103 if (cct->_conf->crush_location.length()) {
104 return update_from_conf();
105 }
106 if (cct->_conf->crush_location_hook.length()) {
107 return update_from_hook();
108 }
109
110 // start with a sane default
111 char hostname[HOST_NAME_MAX + 1];
112 int r = gethostname(hostname, sizeof(hostname));
113 if (r < 0)
114 strcpy(hostname, "unknown_host");
115 // use short hostname
116 for (unsigned i=0; hostname[i]; ++i) {
117 if (hostname[i] == '.') {
118 hostname[i] = '\0';
119 break;
120 }
121 }
122 std::lock_guard l(lock);
123 loc.clear();
124 loc.insert(std::make_pair<std::string,std::string>("host", hostname));
125 loc.insert(std::make_pair<std::string,std::string>("root", "default"));
126 return 0;
127 }
128
129 std::multimap<std::string,std::string> CrushLocation::get_location() const
130 {
131 std::lock_guard l(lock);
132 return loc;
133 }
134
135 std::ostream& operator<<(std::ostream& os, const CrushLocation& loc)
136 {
137 bool first = true;
138 for (auto& [type, pos] : loc.get_location()) {
139 if (first) {
140 first = false;
141 } else {
142 os << ", ";
143 }
144 os << '"' << type << '=' << pos << '"';
145 }
146 return os;
147 }
148
149 }