]> git.proxmox.com Git - ceph.git/blob - ceph/src/crush/CrushLocation.cc
update source to Ceph Pacific 16.2.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 "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"
14
15 #include "common/SubProcess.h"
16
17 #include <vector>
18
19 namespace TOPNSPC::crush {
20
21 int CrushLocation::update_from_conf()
22 {
23 if (cct->_conf->crush_location.length())
24 return _parse(cct->_conf->crush_location);
25 return 0;
26 }
27
28 int CrushLocation::_parse(const std::string& s)
29 {
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);
34 if (r < 0) {
35 lderr(cct) << "warning: crush_location '" << cct->_conf->crush_location
36 << "' does not parse, keeping original crush_location "
37 << loc << dendl;
38 return -EINVAL;
39 }
40 std::lock_guard l(lock);
41 loc.swap(new_crush_location);
42 lgeneric_dout(cct, 10) << "crush_location is " << loc << dendl;
43 return 0;
44 }
45
46 int CrushLocation::update_from_hook()
47 {
48 if (cct->_conf->crush_location_hook.length() == 0)
49 return 0;
50
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 }
99
100 int CrushLocation::init_on_startup()
101 {
102 if (cct->_conf->crush_location.length()) {
103 return update_from_conf();
104 }
105 if (cct->_conf->crush_location_hook.length()) {
106 return update_from_hook();
107 }
108
109 // start with a sane default
110 char hostname[HOST_NAME_MAX + 1];
111 int r = gethostname(hostname, sizeof(hostname));
112 if (r < 0)
113 strcpy(hostname, "unknown_host");
114 // use short hostname
115 for (unsigned i=0; hostname[i]; ++i) {
116 if (hostname[i] == '.') {
117 hostname[i] = '\0';
118 break;
119 }
120 }
121 std::lock_guard l(lock);
122 loc.clear();
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 return 0;
126 }
127
128 std::multimap<std::string,std::string> CrushLocation::get_location() const
129 {
130 std::lock_guard l(lock);
131 return loc;
132 }
133
134 std::ostream& operator<<(std::ostream& os, const CrushLocation& loc)
135 {
136 bool first = true;
137 for (auto& [type, pos] : loc.get_location()) {
138 if (first) {
139 first = false;
140 } else {
141 os << ", ";
142 }
143 os << '"' << type << '=' << pos << '"';
144 }
145 return os;
146 }
147
148 }