]>
git.proxmox.com Git - ceph.git/blob - ceph/src/crimson/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 #include "CrushLocation.h"
6 #include <boost/algorithm/string/trim.hpp>
7 #include <seastar/util/process.hh>
8 #include <seastar/util/later.hh>
10 #include "crush/CrushWrapper.h"
11 #include "crimson/common/log.h"
12 #include "crimson/common/config_proxy.h"
14 static seastar::logger
& logger() {
15 return crimson::get_logger(ceph_subsys_crush
);
18 using namespace crimson::common
;
20 namespace crimson::crush
{
22 seastar::future
<> CrushLocation::update_from_conf()
24 auto crush_location
= local_conf().get_val
<std::string
>("crush_location");
25 if (crush_location
.length()) {
26 _parse(crush_location
);
29 return seastar::now();
32 void CrushLocation::_parse(const std::string
& s
)
34 std::multimap
<std::string
, std::string
> new_crush_location
;
35 std::vector
<std::string
> lvec
;
36 get_str_vec(s
, ";, \t", lvec
);
37 int r
= CrushWrapper::parse_loc_multimap(lvec
, &new_crush_location
);
39 logger().error("CrushWrapper::parse_loc_multimap error, keeping original\
40 crush_location {}", *this);
44 loc
.swap(new_crush_location
);
45 logger().info("{}: crush_location is {}", __func__
, *this);
49 seastar::future
<> CrushLocation::update_from_hook()
51 auto crush_location_hook
= local_conf().get_val
<std::string
>("crush_location_hook");
52 if (crush_location_hook
.length() == 0)
53 return seastar::now();
55 return seastar::file_exists(
57 ).then([this] (bool result
) {
59 std::stringstream errmsg
;
60 errmsg
<< "the user define crush location hook: "
61 << local_conf().get_val
<std::string
>("crush_location_hook")
63 logger().error("{}", errmsg
.str());
64 throw std::runtime_error(errmsg
.str());
67 return seastar::file_accessible(
68 local_conf().get_val
<std::string
>("crush_location_hook"),
69 seastar::access_flags::execute
70 ).then([this] (bool result
) {
72 std::stringstream errmsg
;
73 errmsg
<< "the user define crush location hook: "
74 << local_conf().get_val
<std::string
>("crush_location_hook")
75 << " is not executable.";
76 logger().error("{}", errmsg
.str());
77 throw std::runtime_error(errmsg
.str());
80 seastar::experimental::spawn_parameters params
= {
82 local_conf().get_val
<std::string
>("crush_location_hook"),
84 local_conf()->cluster
,
86 local_conf()->name
.get_id(),
88 local_conf()->name
.get_type_str()
91 return seastar::experimental::spawn_process(
92 local_conf().get_val
<std::string
>("crush_location_hook"),
94 ).then([this] (auto process
) {
95 auto stdout
= process
.stdout();
99 [this](auto& process
, auto& stdout
)
101 return stdout
.read().then([] (seastar::temporary_buffer
<char> buf
) {
102 auto out
= std::string(buf
.get(), buf
.size());
103 boost::algorithm::trim_if(out
, boost::algorithm::is_any_of(" \n\r\t"));
104 return seastar::make_ready_future
<std::string
>(std::move(out
));
105 }).then([&process
, this] (auto out
) {
107 ).then([out
= std::move(out
), this] (auto wstatus
) {
108 auto* exit_signal
= std::get_if
<seastar::experimental::process::wait_signaled
>(&wstatus
);
109 if (exit_signal
!= nullptr) {
110 std::stringstream errmsg
;
111 errmsg
<< "the user define crush location hook: "
112 << local_conf().get_val
<std::string
>("crush_location_hook")
113 << " terminated, terminated signal is "
114 << exit_signal
->terminating_signal
;
115 logger().error("{}", errmsg
.str());
116 throw std::runtime_error(errmsg
.str());
119 auto* exit_status
= std::get_if
<seastar::experimental::process::wait_exited
>(&wstatus
);
120 if (exit_status
->exit_code
!= 0) {
121 std::stringstream errmsg
;
122 errmsg
<< "the user define crush location hook: "
123 << local_conf().get_val
<std::string
>("crush_location_hook")
124 << " execute failed, exit_code is " << exit_status
->exit_code
;
125 logger().error("{}", errmsg
.str());
126 throw std::runtime_error(errmsg
.str());
130 return seastar::now();
139 seastar::future
<> CrushLocation::init_on_startup()
141 if (local_conf().get_val
<std::string
>("crush_location").length()) {
142 return update_from_conf();
144 if (local_conf().get_val
<std::string
>("crush_location_hook").length()) {
145 return update_from_hook();
148 // start with a sane default
149 char hostname
[HOST_NAME_MAX
+ 1];
150 int r
= gethostname(hostname
, sizeof(hostname
));
152 strcpy(hostname
, "unknown_host");
153 // use short hostname
154 for (unsigned i
=0; hostname
[i
]; ++i
) {
155 if (hostname
[i
] == '.') {
162 loc
.insert(std::make_pair
<std::string
, std::string
>("host", hostname
));
163 loc
.insert(std::make_pair
<std::string
, std::string
>("root", "default"));
164 return seastar::now();
167 std::multimap
<std::string
,std::string
> CrushLocation::get_location() const
172 std::ostream
& operator<<(std::ostream
& os
, const CrushLocation
& loc
)
175 for (auto& [type
, pos
] : loc
.get_location()) {
181 os
<< '"' << type
<< '=' << pos
<< '"';