]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include <sys/types.h> | |
5 | #include <unistd.h> | |
6 | ||
7 | #include <iostream> | |
9f95a23c | 8 | #include <random> |
11fdf7f2 TL |
9 | |
10 | #include <seastar/core/app-template.hh> | |
9f95a23c | 11 | #include <seastar/core/print.hh> |
11fdf7f2 | 12 | #include <seastar/core/thread.hh> |
9f95a23c | 13 | #include <seastar/util/std-compat.hh> |
11fdf7f2 | 14 | |
9f95a23c | 15 | #include "auth/KeyRing.h" |
11fdf7f2 | 16 | #include "common/ceph_argparse.h" |
9f95a23c | 17 | #include "crimson/common/buffer_io.h" |
11fdf7f2 | 18 | #include "crimson/common/config_proxy.h" |
9f95a23c TL |
19 | #include "crimson/net/Messenger.h" |
20 | #include "global/pidfile.h" | |
11fdf7f2 TL |
21 | |
22 | #include "osd.h" | |
23 | ||
9f95a23c TL |
24 | using config_t = crimson::common::ConfigProxy; |
25 | namespace fs = seastar::compat::filesystem; | |
11fdf7f2 TL |
26 | |
27 | void usage(const char* prog) { | |
9f95a23c TL |
28 | std::cout << "usage: " << prog << " -i <ID>\n" |
29 | << " --help-seastar show Seastar help messages\n"; | |
11fdf7f2 TL |
30 | generic_server_usage(); |
31 | } | |
32 | ||
9f95a23c TL |
33 | auto partition_args(seastar::app_template& app, char** argv_begin, char** argv_end) |
34 | { | |
35 | namespace bpo = boost::program_options; | |
36 | // collect all options consumed by seastar::app_template | |
37 | auto parsed = bpo::command_line_parser(std::distance(argv_begin, argv_end), | |
38 | argv_begin) | |
39 | .options(app.get_options_description()).allow_unregistered().run(); | |
40 | auto unknown_args = bpo::collect_unrecognized(parsed.options, | |
41 | bpo::include_positional); | |
42 | std::vector<const char*> ceph_args, app_args; | |
43 | // ceph_argparse_early_args() and | |
44 | // seastar::smp::get_options_description() use "-c" for different | |
45 | // options. and ceph wins | |
46 | auto consume_conf_arg = [&](char** argv) { | |
47 | if (std::strcmp(*argv, "-c") == 0) { | |
48 | ceph_args.push_back(*argv++); | |
49 | if (argv != argv_end) { | |
50 | ceph_args.push_back(*argv++); | |
51 | } | |
52 | } | |
53 | return argv; | |
54 | }; | |
55 | auto unknown = unknown_args.begin(); | |
56 | auto consume_unknown_arg = [&](char** argv) { | |
57 | for (; unknown != unknown_args.end() && | |
58 | argv != argv_end && | |
59 | *unknown == *argv; ++argv, ++unknown) { | |
60 | if (std::strcmp(*argv, "--help-seastar") == 0) { | |
61 | app_args.push_back("--help"); | |
62 | } else { | |
63 | ceph_args.push_back(*argv); | |
64 | } | |
65 | } | |
66 | return argv; | |
67 | }; | |
68 | for (auto argv = argv_begin; argv != argv_end;) { | |
69 | if (auto next_arg = consume_conf_arg(argv); next_arg != argv) { | |
70 | argv = next_arg; | |
71 | } else if (auto next_arg = consume_unknown_arg(argv); next_arg != argv) { | |
72 | argv = next_arg; | |
73 | } else { | |
74 | app_args.push_back(*argv++); | |
75 | } | |
76 | } | |
77 | return make_pair(std::move(ceph_args), std::move(app_args)); | |
78 | } | |
79 | ||
80 | using crimson::common::local_conf; | |
81 | ||
82 | seastar::future<> make_keyring() | |
83 | { | |
84 | const auto path = local_conf().get_val<string>("keyring"); | |
85 | return seastar::file_exists(path).then([path](bool exists) { | |
86 | KeyRing keyring; | |
87 | EntityName name{local_conf()->name}; | |
88 | EntityAuth auth; | |
89 | if (exists && | |
90 | keyring.load(nullptr, path) == 0 && | |
91 | keyring.get_auth(name, auth)) { | |
92 | seastar::fprint(std::cerr, "already have key in keyring: %s\n", path); | |
93 | return seastar::now(); | |
94 | } else { | |
95 | auth.key.create(std::make_unique<CephContext>().get(), CEPH_CRYPTO_AES); | |
96 | keyring.add(name, auth); | |
97 | bufferlist bl; | |
98 | keyring.encode_plaintext(bl); | |
99 | const auto permissions = (seastar::file_permissions::user_read | | |
100 | seastar::file_permissions::user_write); | |
101 | return ceph::buffer::write_file(std::move(bl), path, permissions); | |
102 | } | |
103 | }).handle_exception_type([path](const fs::filesystem_error& e) { | |
104 | seastar::fprint(std::cerr, "FATAL: writing new keyring to %s: %s\n", path, e.what()); | |
105 | throw e; | |
106 | }); | |
107 | } | |
108 | ||
109 | uint64_t get_nonce() | |
110 | { | |
111 | if (auto pid = getpid(); pid != 1) { | |
112 | return pid; | |
113 | } else { | |
114 | // we're running in a container; use a random number instead! | |
115 | std::random_device rd; | |
116 | std::default_random_engine rng{rd()}; | |
117 | return std::uniform_int_distribution<uint64_t>{}(rng); | |
118 | } | |
119 | } | |
120 | ||
11fdf7f2 TL |
121 | int main(int argc, char* argv[]) |
122 | { | |
9f95a23c TL |
123 | seastar::app_template app; |
124 | app.add_options() | |
125 | ("mkkey", "generate a new secret key. " | |
126 | "This is normally used in combination with --mkfs") | |
127 | ("mkfs", "create a [new] data directory") | |
128 | ("debug", "enable debug output on all loggers"); | |
129 | ||
130 | auto [ceph_args, app_args] = partition_args(app, argv, argv + argc); | |
131 | if (ceph_argparse_need_usage(ceph_args) && | |
132 | std::find(app_args.begin(), app_args.end(), "--help") == app_args.end()) { | |
11fdf7f2 TL |
133 | usage(argv[0]); |
134 | return EXIT_SUCCESS; | |
135 | } | |
9f95a23c | 136 | std::string cluster_name; |
11fdf7f2 TL |
137 | std::string conf_file_list; |
138 | // ceph_argparse_early_args() could _exit(), while local_conf() won't ready | |
139 | // until it's started. so do the boilerplate-settings parsing here. | |
9f95a23c | 140 | auto init_params = ceph_argparse_early_args(ceph_args, |
11fdf7f2 | 141 | CEPH_ENTITY_TYPE_OSD, |
9f95a23c | 142 | &cluster_name, |
11fdf7f2 | 143 | &conf_file_list); |
9f95a23c TL |
144 | seastar::sharded<crimson::osd::OSD> osd; |
145 | using crimson::common::sharded_conf; | |
146 | using crimson::common::sharded_perf_coll; | |
11fdf7f2 | 147 | try { |
9f95a23c TL |
148 | return app.run_deprecated(app_args.size(), const_cast<char**>(app_args.data()), |
149 | [&, &ceph_args=ceph_args] { | |
11fdf7f2 | 150 | auto& config = app.configuration(); |
9f95a23c TL |
151 | return seastar::async([&] { |
152 | if (config.count("debug")) { | |
153 | seastar::global_logger_registry().set_all_loggers_level( | |
154 | seastar::log_level::debug | |
155 | ); | |
156 | } | |
157 | sharded_conf().start(init_params.name, cluster_name).get(); | |
158 | seastar::engine().at_exit([] { | |
159 | return sharded_conf().stop(); | |
160 | }); | |
161 | sharded_perf_coll().start().get(); | |
162 | seastar::engine().at_exit([] { | |
163 | return sharded_perf_coll().stop(); | |
164 | }); | |
165 | local_conf().parse_config_files(conf_file_list).get(); | |
166 | local_conf().parse_argv(ceph_args).get(); | |
167 | pidfile_write(local_conf()->pid_file); | |
168 | const int whoami = std::stoi(local_conf()->name.get_id()); | |
169 | const auto nonce = get_nonce(); | |
170 | crimson::net::MessengerRef cluster_msgr, client_msgr; | |
171 | crimson::net::MessengerRef hb_front_msgr, hb_back_msgr; | |
172 | for (auto [msgr, name] : {make_pair(std::ref(cluster_msgr), "cluster"s), | |
173 | make_pair(std::ref(client_msgr), "client"s), | |
174 | make_pair(std::ref(hb_front_msgr), "hb_front"s), | |
175 | make_pair(std::ref(hb_back_msgr), "hb_back"s)}) { | |
176 | msgr = crimson::net::Messenger::create(entity_name_t::OSD(whoami), name, | |
177 | nonce); | |
178 | if (local_conf()->ms_crc_data) { | |
179 | msgr->set_crc_data(); | |
180 | } | |
181 | if (local_conf()->ms_crc_header) { | |
182 | msgr->set_crc_header(); | |
183 | } | |
184 | } | |
185 | osd.start_single(whoami, nonce, | |
186 | cluster_msgr, client_msgr, | |
187 | hb_front_msgr, hb_back_msgr).get(); | |
188 | if (config.count("mkkey")) { | |
189 | make_keyring().handle_exception([](std::exception_ptr) { | |
190 | seastar::engine().exit(1); | |
191 | }).get(); | |
192 | } | |
193 | if (config.count("mkfs")) { | |
194 | osd.invoke_on( | |
195 | 0, | |
196 | &crimson::osd::OSD::mkfs, | |
197 | local_conf().get_val<uuid_d>("osd_uuid"), | |
198 | local_conf().get_val<uuid_d>("fsid")).get(); | |
199 | } | |
200 | seastar::engine().at_exit([&] { | |
201 | return osd.stop(); | |
202 | }); | |
203 | if (config.count("mkkey") || config.count("mkfs")) { | |
204 | seastar::engine().exit(0); | |
11fdf7f2 | 205 | } else { |
9f95a23c | 206 | osd.invoke_on(0, &crimson::osd::OSD::start).get(); |
11fdf7f2 TL |
207 | } |
208 | }); | |
209 | }); | |
210 | } catch (...) { | |
211 | seastar::fprint(std::cerr, "FATAL: Exception during startup, aborting: %s\n", std::current_exception()); | |
212 | return EXIT_FAILURE; | |
213 | } | |
214 | } | |
215 | ||
216 | /* | |
217 | * Local Variables: | |
218 | * compile-command: "make -j4 \ | |
219 | * -C ../../../build \ | |
220 | * crimson-osd" | |
221 | * End: | |
222 | */ |