0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
serverup.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-2015 Hypertable, Inc.
3  *
4  * This file is part of Hypertable.
5  *
6  * Hypertable is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 3
9  * of the License, or any later version.
10  *
11  * Hypertable is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21 
22 #include <Common/Compat.h>
23 
24 #ifdef HT_WITH_THRIFT
25 #include <ThriftBroker/Config.h>
26 #include <ThriftBroker/Client.h>
27 #endif
28 
29 #include <Hyperspace/Session.h>
30 
31 #include <Hypertable/Lib/Config.h>
35 
36 #include <FsBroker/Lib/Client.h>
37 
39 #include <AsyncComm/Comm.h>
42 
43 #include <Common/Config.h>
44 #include <Common/Error.h>
45 #include <Common/InetAddr.h>
46 #include <Common/Logger.h>
47 #include <Common/Init.h>
48 #include <Common/Status.h>
49 #include <Common/Timer.h>
50 #include <Common/Usage.h>
51 
52 #include <boost/algorithm/string.hpp>
53 
54 #include <cstdlib>
55 #include <iostream>
56 #include <string>
57 
58 extern "C" {
59 #include <netdb.h>
60 #include <sys/types.h>
61 #include <signal.h>
62 }
63 
64 using namespace Hypertable;
65 using namespace Hypertable::Lib;
66 using namespace Config;
67 using namespace std;
68 
69 namespace {
70 
71  const char *usage =
72  "Usage: serverup [options] <server-name>\n\n"
73  "Description:\n"
74  " This program checks to see if the server, specified by <server-name>\n"
75  " is up. return 0 if true, 1 otherwise. <server-name> may be one of the\n"
76  " following values: fsbroker, hyperspace, master, global-master, \n"
77  " rangeserver, thriftbroker\n\n"
78  " master: checks for a master running on localhost\n"
79  " global-master: checks for a master running in the cluster (address is\n"
80  " fetched from hyperspace)\n"
81  "Options";
82 
83  struct AppPolicy : Config::Policy {
84  static void init_options() {
85  cmdline_desc(usage).add_options()
86  ("wait", i32()->default_value(2000), "Check wait time in ms")
87  ("host", str(), "Specifies the hostname of the server(s)")
88  ("display-address", boo()->default_value(false),
89  "Displays hostname and port of the server(s), then exits")
90  ;
91  cmdline_hidden_desc().add_options()("server-name", str(), "");
92  cmdline_positional_desc().add("server-name", -1);
93  }
94  static void init() {
95  // we want to override the default behavior that verbose
96  // turns on debugging by clearing the defaulted flag
97  if (defaulted("logging-level"))
98  properties->set("logging-level", String("fatal"));
99  }
100  };
101 
102 #ifdef HT_WITH_THRIFT
103  typedef Meta::list<AppPolicy, FsClientPolicy, HyperspaceClientPolicy,
106 #else
107  typedef Meta::list<AppPolicy, FsClientPolicy, HyperspaceClientPolicy,
108  MasterClientPolicy, RangeServerClientPolicy, DefaultCommPolicy>
109  Policies;
110 #endif
111 
112  void
113  wait_for_connection(const char *server, ConnectionManagerPtr &conn_mgr,
114  InetAddr &addr, int timeout_ms, int wait_ms) {
115  HT_DEBUG_OUT <<"Checking "<< server <<" at "<< addr << HT_END;
116 
117  conn_mgr->add(addr, timeout_ms, server);
118 
119  if (!conn_mgr->wait_for_connection(addr, wait_ms))
120  HT_THROWF(Error::REQUEST_TIMEOUT, "connecting to %s", server);
121  }
122 
123  void check_fsbroker(ConnectionManagerPtr &conn_mgr, uint32_t wait_ms) {
124  HT_DEBUG_OUT << "Checking fsbroker at " << get_str("fs-host")
125  << ':' << get_i16("fs-port") << HT_END;
126 
127  if (properties->has("host")) {
128  properties->set("FsBroker.Host", properties->get_str("host"));
129  properties->set("fs-host", properties->get_str("host"));
130  }
131 
132  // Backward compatibility
133  if (properties->has("DfsBroker.Host")) {
134  properties->set("FsBroker.Host", properties->get_str("DfsBroker.Host"));
135  properties->set("fs-host", properties->get_str("DfsBroker.Host"));
136  }
137  if (properties->has("DfsBroker.Port")) {
138  properties->set("FsBroker.Port", properties->get_i16("DfsBroker.Port"));
139  properties->set("fs-port", properties->get_i16("DfsBroker.Port"));
140  }
141 
142  if (get_bool("display-address")) {
143  std::cout << get_str("fs-host") << ":" << get_i16("fs-port")
144  << std::endl;
145  quick_exit(EXIT_SUCCESS);
146  }
147 
148  FsBroker::Lib::ClientPtr fs = std::make_shared<FsBroker::Lib::Client>(conn_mgr, properties);
149 
150  if (!fs->wait_for_connection(wait_ms))
151  HT_THROW(Error::REQUEST_TIMEOUT, "connecting to fsbroker");
152 
153  try {
154  Status::Code code;
155  string output;
156  Status status;
157  fs->status(status);
158  status.get(&code, output);
159  if (code != Status::Code::OK && code != Status::Code::WARNING)
161  }
162  catch (Exception &e) {
163  HT_ERRORF("Status check: %s - %s", Error::get_text(e.code()), e.what());
164  quick_exit(EXIT_FAILURE);
165  }
166  }
167 
168  Hyperspace::SessionPtr hyperspace;
169 
170  void check_hyperspace(ConnectionManagerPtr &conn_mgr, uint32_t max_wait_ms) {
171  HT_DEBUG_OUT << "Checking hyperspace"<< HT_END;
172  Timer timer(max_wait_ms, true);
173  int error;
174 
175  String host = "localhost";
176  if (properties->has("host")) {
177  host = properties->get_str("host");
178  std::vector<String> vec;
179  vec.push_back(host);
180  properties->set("Hyperspace.Replica.Host", vec);
181  }
182 
183  if (get_bool("display-address")) {
184  std::cout << host << ":" <<
185  properties->get_i16("Hyperspace.Replica.Port") << std::endl;
186  quick_exit(EXIT_SUCCESS);
187  }
188 
189  hyperspace = make_shared<Hyperspace::Session>(conn_mgr->get_comm(), properties);
190 
191  if (!hyperspace->wait_for_connection(max_wait_ms))
192  HT_THROW(Error::REQUEST_TIMEOUT, "connecting to hyperspace");
193 
194  Status status;
195  error = hyperspace->status(status, &timer);
196  if (error == Error::OK) {
197  if (status.get() != Status::Code::OK)
198  HT_THROW(Error::FAILED_EXPECTATION, "getting hyperspace status");
199  }
200  else if (error != Error::HYPERSPACE_NOT_MASTER_LOCATION) {
201  HT_THROW(error, "getting hyperspace status");
202  }
203  }
204 
205  void check_global_master(ConnectionManagerPtr &conn_mgr, uint32_t wait_ms) {
206  HT_DEBUG_OUT << "Checking master via hyperspace" << HT_END;
207  Timer timer(wait_ms, true);
208 
209  if (get_bool("display-address")) {
210  std::cout << get_str("Hypertable.Master.Host") << ":" <<
211  get_i16("Hypertable.Master.Port") << std::endl;
212  quick_exit(EXIT_SUCCESS);
213  }
214 
215  if (!hyperspace) {
216  hyperspace = make_shared<Hyperspace::Session>(conn_mgr->get_comm(), properties);
217  if (!hyperspace->wait_for_connection(wait_ms))
218  HT_THROW(Error::REQUEST_TIMEOUT, "connecting to hyperspace");
219  }
220 
221  ApplicationQueueInterfacePtr app_queue = make_shared<ApplicationQueue>(1);
222 
223  String toplevel_dir = properties->get_str("Hypertable.Directory");
224  boost::trim_if(toplevel_dir, boost::is_any_of("/"));
225  toplevel_dir = String("/") + toplevel_dir;
226 
227  Lib::Master::Client *master =
228  new Lib::Master::Client(conn_mgr, hyperspace,
229  toplevel_dir, wait_ms, app_queue,
231 
232  if (!master->wait_for_connection(wait_ms))
233  HT_THROW(Error::REQUEST_TIMEOUT, "connecting to master");
234 
235  Status status;
236  Status::Code code;
237  string text;
238  master->status(status, &timer);
239  status.get(&code, text);
240  if (code != Status::Code::OK)
242  }
243 
244  void check_master(ConnectionManagerPtr &conn_mgr, uint32_t wait_ms) {
245  Timer timer(wait_ms, true);
246  uint16_t port = properties->get_i16("Hypertable.Master.Port");
247 
248  const char *host;
249  if (properties->has("host"))
250  host = properties->get_str("host").c_str();
251  else
252  host = "localhost";
253 
254  if (get_bool("display-address")) {
255  std::cout << host << ":" << port << std::endl;
256  quick_exit(EXIT_SUCCESS);
257  }
258 
259  HT_DEBUG_OUT << "Checking master on " << host << ":" << port << HT_END;
260  InetAddr addr(host, port);
261 
262  Lib::Master::Client *master = new Lib::Master::Client(conn_mgr, addr, wait_ms);
263 
264  if (!master->wait_for_connection(wait_ms)) {
265  if (strcmp(host, "localhost") && strcmp(host, "127.0.0.1"))
266  HT_THROW(Error::REQUEST_TIMEOUT, "connecting to master");
267 
268  String pidstr;
269  String pid_file = System::install_dir + "/run/Master.pid";
270  if (!FileUtils::read(pid_file, pidstr))
271  HT_THROW(Error::FILE_NOT_FOUND, pid_file);
272  pid_t pid = (pid_t)strtoul(pidstr.c_str(), 0, 0);
273  if (pid <= 0)
274  HT_THROW(Error::REQUEST_TIMEOUT, "connecting to master");
275  // (kill(pid, 0) does not send any signal but checks if the process exists
276  if (::kill(pid, 0) < 0)
277  HT_THROW(Error::REQUEST_TIMEOUT, "connecting to master");
278  }
279  else {
280  Status status;
281  Status::Code code;
282  string text;
283  master->status(status, &timer);
284  status.get(&code, text);
285  if (code != Status::Code::OK)
287  }
288  }
289 
290  void check_rangeserver(ConnectionManagerPtr &conn_mgr, uint32_t wait_ms) {
291  HT_DEBUG_OUT <<"Checking rangeserver at "<< get_str("rs-host")
292  <<':'<< get_i16("rs-port") << HT_END;
293 
294  Status::Code ready_status =
295  Status::string_to_code(properties->get_str("Hypertable.RangeServer.ReadyStatus"));
296 
297  if (properties->has("host"))
298  properties->set("rs-host", properties->get_str("host"));
299 
300  if (get_bool("display-address")) {
301  std::cout << get_str("rs-host") << ":" << get_i16("rs-port") << std::endl;
302  quick_exit(EXIT_SUCCESS);
303  }
304 
305  InetAddr addr(get_str("rs-host"), get_i16("rs-port"));
306 
307  wait_for_connection("range server", conn_mgr, addr, wait_ms, wait_ms);
308 
309  RangeServer::ClientPtr range_server
310  = make_shared<RangeServer::Client>(conn_mgr->get_comm(), wait_ms);
311  Timer timer(wait_ms, true);
312  Status status;
313  range_server->status(addr, status, timer);
314  Status::Code code;
315  string text;
316  status.get(&code, text);
317  if (code > ready_status)
319  }
320 
321  void check_thriftbroker(ConnectionManagerPtr &conn_mgr, int wait_ms) {
322 #ifdef HT_WITH_THRIFT
323  if (properties->has("host"))
324  properties->set("thrift-host", properties->get_str("host"));
325 
326  if (get_bool("display-address")) {
327  std::cout << get_str("thrift-host") << ":" << get_i16("thrift-port")
328  << std::endl;
329  quick_exit(EXIT_SUCCESS);
330  }
331 
332  String table_id;
333  InetAddr addr(get_str("thrift-host"), get_i16("thrift-port"));
334 
335  try {
336  Thrift::Client client(get_str("thrift-host"), get_i16("thrift-port"));
337  ThriftGen::Namespace ns = client.open_namespace("sys");
338  client.get_table_id(table_id, ns, "METADATA");
339  client.namespace_close(ns);
340  }
341  catch (ThriftGen::ClientException &e) {
342  HT_THROW(e.code, e.message);
343  }
344  catch (std::exception &e) {
345  HT_THROW(Error::EXTERNAL, e.what());
346  }
348 #else
349  HT_THROW(Error::FAILED_EXPECTATION, "Thrift support not installed");
350 #endif
351  }
352 
353 } // local namespace
354 
355 #define CHECK_SERVER(_server_) do { \
356  try { check_##_server_(conn_mgr, wait_ms); } catch (Exception &e) { \
357  if (verbose) { \
358  HT_DEBUG_OUT << e << HT_END; \
359  cout << #_server_ <<" - down" << endl; \
360  } \
361  ++down; \
362  break; \
363  } \
364  if (verbose) cout << #_server_ <<" - up" << endl; \
365 } while (0)
366 
367 
368 int main(int argc, char **argv) {
369  int down = 0;
370 
371  try {
372  init_with_policies<Policies>(argc, argv);
373 
374  bool silent = get_bool("silent");
375  uint32_t wait_ms = get_i32("wait");
376  String server_name = get("server-name", String());
377  bool verbose = get_bool("verbose");
378 
379  ConnectionManagerPtr conn_mgr = make_shared<ConnectionManager>();
380  conn_mgr->set_quiet_mode(silent);
381 
382  properties->set("FsBroker.Timeout", (int32_t)wait_ms);
383 
384  if (server_name == "fsbroker") {
385  CHECK_SERVER(fsbroker);
386  }
387  else if (server_name == "hyperspace") {
388  CHECK_SERVER(hyperspace);
389  }
390  else if (server_name == "global-master" || server_name == "global_master") {
391  CHECK_SERVER(global_master);
392  }
393  else if (server_name == "master") {
394  CHECK_SERVER(master);
395  }
396  else if (server_name == "rangeserver") {
397  CHECK_SERVER(rangeserver);
398  }
399  else if (server_name == "thriftbroker") {
400  CHECK_SERVER(thriftbroker);
401  }
402  else {
403  CHECK_SERVER(fsbroker);
404  CHECK_SERVER(hyperspace);
405  //CHECK_SERVER(master);
406  CHECK_SERVER(global_master);
407  CHECK_SERVER(rangeserver);
408 #ifdef HT_WITH_THRIFT
409  CHECK_SERVER(thriftbroker);
410 #endif
411  }
412 
413  if (!silent)
414  cout << (down ? "false" : "true") << endl;
415  }
416  catch (Exception &e) {
417  HT_ERROR_OUT << e << HT_END;
418  quick_exit(EXIT_FAILURE);
419  }
420  quick_exit(down); // ditto
421 }
Interface and base of config policy.
Definition: Config.h:149
static const char * METADATA_ID
Holds Nagios-style program status information.
Definition: Status.h:42
PropertiesPtr properties
This singleton map stores all options.
Definition: Config.cc:47
static bool read(const String &fname, String &contents)
Reads a whole file into a String.
Definition: FileUtils.cc:59
std::string String
A String is simply a typedef to std::string.
Definition: String.h:44
Declarations for Status.
Helper class for printing usage banners on the command line.
void init(int argc, char *argv[], const Desc *desc=NULL)
Initialize with default policy.
Definition: Init.h:95
Declarations for TableIdentifier and TableIdentifierManaged.
Po::typed_value< String > * str(String *v=0)
Definition: Properties.h:166
STL namespace.
Declarations for RangeServerClient.
Code
Enumeration for status codes.
Definition: Status.h:47
bool wait_for_connection(uint32_t max_wait_ms)
Definition: Client.cc:1041
Desc & cmdline_desc(const char *usage)
A macro which definds global functions like get_bool(), get_str(), get_i16() etc. ...
Definition: Config.cc:72
#define HT_EXPECT(_e_, _code_)
Definition: Logger.h:388
std::shared_ptr< Session > SessionPtr
Definition: Session.h:734
const char * get_text(int error)
Returns a descriptive error message.
Definition: Error.cc:330
bool status(ContextPtr &context, Timer &timer, Status &status)
Runs a status check on the master.
Definition: Utility.cc:408
Encapsulate an internet address.
Definition: InetAddr.h:66
Po::typed_value< int32_t > * i32(int32_t *v=0)
Definition: Properties.h:178
std::shared_ptr< Client > ClientPtr
Smart pointer to Client.
Definition: Client.h:594
std::shared_ptr< Client > ClientPtr
Smart pointer to Client.
Definition: Client.h:233
Helpers to compose init policies; allow to combine two policies into one.
Definition: Config.h:174
int main(int argc, char **argv)
Definition: serverup.cc:368
A timer class to keep timeout states across AsyncComm related calls.
Logging routines and macros.
Compatibility Macros for C/C++.
Po::typed_value< bool > * boo(bool *v=0)
Definition: Properties.h:162
Initialization helper for applications.
#define HT_END
Definition: Logger.h:220
std::shared_ptr< ApplicationQueueInterface > ApplicationQueueInterfacePtr
Smart pointer to ApplicationQueueInterface.
bool defaulted(const String &name)
Check if a configuration value is defaulted.
Definition: Config.h:67
#define HT_ERROR_OUT
Definition: Logger.h:301
Hypertable library.
Definition: CellInterval.h:30
Hypertable definitions
void status(Status &status, Timer *timer=0)
Definition: Client.cc:377
Declarations for ConnectionManager.
Declarations for Comm.
#define HT_THROWF(_code_, _fmt_,...)
Definition: Error.h:490
static Code string_to_code(std::string str)
Definition: Status.cc:53
void get(Code *code, std::string &text) const
Gets status code and text.
Definition: Status.h:111
Internet address wrapper classes and utility functions.
Meta::list< MyPolicy, DefaultPolicy > Policies
Declarations for ReactorFactory.
A timer class to keep timeout states across AsyncComm related calls.
Definition: Timer.h:44
static String install_dir
The installation directory.
Definition: System.h:114
This is a generic exception class for Hypertable.
Definition: Error.h:314
std::shared_ptr< DispatchHandler > DispatchHandlerPtr
Smart pointer to DispatchHandler.
Declarations for MasterClient This file contains declarations for MasterClient, a client interface cl...
Client interface to Master.
Definition: Client.h:80
#define HT_ERRORF(msg,...)
Definition: Logger.h:300
Declarations for ApplicationQueue.
Configuration settings.
std::shared_ptr< ConnectionManager > ConnectionManagerPtr
Smart pointer to ConnectionManager.
Desc & cmdline_hidden_desc()
Get the command line hidden options description (for positional options)
Definition: Config.cc:81
std::shared_ptr< ConnectionInitializer > ConnectionInitializerPtr
Smart pointer to ConnectionInitializer.
PositionalDesc & cmdline_positional_desc()
Get the command line positional options description.
Definition: Config.cc:90
Error codes, Exception handling, error logging.
#define HT_THROW(_code_, _msg_)
Definition: Error.h:478
A client for the ThriftBroker.
Definition: Client.h:59
#define CHECK_SERVER(_server_)
Definition: serverup.cc:355
Declarations for Client.
#define HT_DEBUG_OUT
Definition: Logger.h:261
int code() const
Returns the error code.
Definition: Error.h:391