CernVM-FS  2.12.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cvmfs_talk.cc
Go to the documentation of this file.
1 
7 #include <errno.h>
8 #include <unistd.h>
9 
10 #include <cassert>
11 #include <cstring>
12 #include <string>
13 #include <vector>
14 
15 #include "options.h"
16 #include "util/logging.h"
17 #include "util/pointer.h"
18 #include "util/posix.h"
19 #include "util/string.h"
20 
21 
22 struct InstanceInfo {
23  bool IsDefined() {
24  return !socket_path.empty() || !instance_name.empty();
25  }
26 
27  // Called at most once by DeterminePath
28  static std::string GetDefaultDomain() {
29  std::string result;
30  BashOptionsManager options_mgr;
31  options_mgr.ParseDefault("");
32  bool retval = options_mgr.GetValue("CVMFS_DEFAULT_DOMAIN", &result);
33  if (!retval) {
35  "Error: could not determine CVMFS_DEFAULT_DOMAIN");
36  }
37  return result;
38  }
39 
40  bool DeterminePaths() {
41  std::string fqrn = instance_name;
42  if (fqrn.find('.') == std::string::npos) {
43  static std::string default_domain = GetDefaultDomain();
44  fqrn = fqrn + "." + default_domain;
45  }
46 
47  BashOptionsManager options_mgr;
48  options_mgr.ParseDefault(fqrn);
49  if (!options_mgr.GetValue("CVMFS_WORKSPACE", &workspace)) {
50  if (!options_mgr.GetValue("CVMFS_CACHE_DIR", &workspace)) {
51  bool retval = options_mgr.GetValue("CVMFS_CACHE_BASE", &workspace);
52  if (!retval) {
54  "CVMFS_WORKSPACE, CVMFS_CACHE_DIR, and CVMFS_CACHE_BASE "
55  "missing");
56  return false;
57  }
58 
59  std::string optarg;
60  if (options_mgr.GetValue("CVMFS_SHARED_CACHE", &optarg) &&
61  options_mgr.IsOn(optarg))
62  {
63  workspace += "/shared";
64  } else {
65  workspace += "/" + fqrn;
66  }
67  }
68  }
69 
70  socket_path = workspace + "/cvmfs_io." + fqrn;
71  return true;
72  }
73 
74  bool CompleteInfo() {
75  assert(IsDefined());
76 
77  if (socket_path.empty()) {
78  bool retval = DeterminePaths();
79  if (!retval)
80  return false;
81  identifier = "instance '" + instance_name + "' active in " + workspace;
82  } else {
84  identifier = "instance listening at " + socket_path;
85  }
86  return true;
87  }
88 
89  std::string socket_path;
90  std::string instance_name;
91  std::string workspace;
92  std::string identifier;
93 };
94 
95 
96 static bool ReadResponse(int fd) {
97  std::string line;
98  char buf;
99  int retval;
100  while ((retval = read(fd, &buf, 1)) == 1) {
101  if (buf == '\n') {
102  LogCvmfs(kLogCvmfs, kLogStdout, "%s", line.c_str());
103  line.clear();
104  continue;
105  }
106  line.push_back(buf);
107  }
108  return retval == 0;
109 }
110 
111 
112 bool SendCommand(const std::string &command, InstanceInfo instance_info) {
113  bool retval = instance_info.CompleteInfo();
114  if (!retval) return false;
115 
116  int fd = ConnectSocket(instance_info.socket_path);
117  if (fd < 0) {
118  if (errno == ENOENT) {
120  "Seems like CernVM-FS is not running in %s (not found: %s)",
121  instance_info.workspace.c_str(),
122  instance_info.socket_path.c_str());
123  } else {
124  LogCvmfs(kLogCvmfs, kLogStderr, "Could not access %s (%d - %s)",
125  instance_info.identifier.c_str(), errno, strerror(errno));
126  }
127  return false;
128  }
129 
130  WritePipe(fd, command.data(), command.size());
131  retval = ReadResponse(fd);
132  close(fd);
133 
134  if (!retval) {
135  LogCvmfs(kLogCvmfs, kLogStderr, "Broken connection to %s (%d - %s)",
136  instance_info.identifier.c_str(), errno, strerror(errno));
137  return false;
138  }
139  return true;
140 }
141 
142 
143 static void Usage(const std::string &exe) {
145  "Usage: %s [-i instance | -p socket] <command> \n"
146  " By default, iterate through all instances defined in \n"
147  " CVMFS_REPOSITORIES \n"
148  "\n"
149  "Example: \n"
150  " %s -i atlas.cern.ch pid \n"
151  "\n"
152  "Commands: \n"
153  " tracebuffer flush flushes the trace buffer to disk \n"
154  " cache instance describes the active cache manager \n"
155  " cache size gets current size of file cache \n"
156  " cache list gets files in cache \n"
157  " cache list pinned gets pinned file catalogs in cache \n"
158  " cache list catalogs gets all file catalogs in cache \n"
159  " cleanup <MB> cleans file cache until size <= <MB> \n"
160  " cleanup rate <period> n.o. cleanups in the last <period> min \n"
161  " evict <path> removes <path> from the cache \n"
162  " pin <path> pins <path> in the cache \n"
163  " mountpoint returns the mount point \n"
164  " device id returns major:minor virtual device id \n"
165  " on Linux and 0:0 on macOS \n"
166  " remount [sync] look for new catalogs \n"
167  " revision gets the repository revision \n"
168  " max ttl info gets the maximum ttl \n"
169  " max ttl set <minutes> sets the maximum ttl \n"
170  " nameserver get get the DNS server \n"
171  " nameserver set <host> sets a DNS server \n"
172  " host info get host chain and their rtt, \n"
173  " if already probed \n"
174  " host probe orders the host chain according to rtt \n"
175  " host probe geo let Stratum 1s order the host chain and \n"
176  " fallback proxies using the Geo-API \n"
177  " host switch switches to the next host in the chain \n"
178  " host set <host list> sets a new host chain \n"
179  " proxy info gets load-balance proxy groups \n"
180  " proxy rebalance randomly selects a new proxy server \n"
181  " from the current load-balance group \n"
182  " proxy group switch switches to the next load-balance \n"
183  " proxy group in the chain \n"
184  " proxy set <proxy list> sets a new chain of load-balance proxy \n"
185  " groups (not including fallback proxies) \n"
186  " proxy fallback <list> sets a new list of fallback proxies \n"
187  " external host info gets info about external host chain \n"
188  " external host switch switches to the next external host \n"
189  " external host set \n"
190  " <host list> sets external host chain \n"
191  " external proxy info gets info about external proxy groups \n"
192  " external proxy set \n"
193  " <proxy list> sets chain of external proxy groups \n"
194  " timeout info gets the network timeouts \n"
195  " timeout set \n"
196  " <proxy> <direct> sets the network timeouts in seconds \n"
197  " pid gets the pid \n"
198  " pid cachemgr gets the pid of the shared cache manager \n"
199  " pid watchdog gets the pid of the crash handler process\n"
200  " parameters dumps the effective parameters \n"
201  " reset error counters resets the counter for I/O errors \n"
202  " hotpatch history shows timestamps and version info of \n"
203  " loaded (hotpatched) Fuse modules \n"
204  " version gets cvmfs version \n"
205  " version patchlevel gets cvmfs patchlevel \n"
206  " open catalogs shows information about currently \n"
207  " loaded catalogs (_not_ all cached ones) \n"
208  " latency show the latencies of different fuse \n"
209  " calls (requires CVMFS_INSTRUMENT_FUSE) \n"
210  "\n",
211  exe.c_str(), exe.c_str());
212 }
213 
214 
215 int main(int argc, char *argv[]) {
216  InstanceInfo instance_info;
217  std::string command;
218 
219  int c;
220  // 's' for socket would have been a better option letter but we keep 'p'
221  // for backwards compatibility. The '+' at the beginning of the option string
222  // prevents permutation of the option and non-option arguments.
223  while ((c = getopt(argc, argv, "+hi:p:")) != -1) {
224  switch (c) {
225  case 'h':
226  Usage(argv[0]);
227  return 0;
228  case 'p':
229  instance_info.socket_path = optarg;
230  break;
231  case 'i':
232  instance_info.instance_name = optarg;
233  break;
234  case '?':
235  default:
236  Usage(argv[0]);
237  return 1;
238  }
239  }
240 
241  for (; optind < argc; ++optind) {
242  command += argv[optind];
243  if (optind < (argc - 1))
244  command.push_back(' ');
245  }
246  if (command.empty()) {
247  Usage(argv[0]);
248  return 1;
249  }
250 
251  int retcode = 0;
252  if (!instance_info.IsDefined()) {
253  BashOptionsManager options_mgr;
254  options_mgr.ParseDefault("");
255  std::string opt_repos;
256  options_mgr.GetValue("CVMFS_REPOSITORIES", &opt_repos);
257  std::vector<std::string> repos = SplitString(opt_repos, ',');
258  bool is_empty_repo_list = true;
259  for (unsigned i = 0; i < repos.size(); ++i) {
260  if (repos[i].empty())
261  continue;
262  is_empty_repo_list = false;
263  instance_info.instance_name = repos[i];
264  LogCvmfs(kLogCvmfs, kLogStdout, "%s:", repos[i].c_str());
265  bool retval = SendCommand(command, instance_info);
266  if (!retval) retcode = 1;
267  }
268  if (is_empty_repo_list) {
270  "Warning: no instance was specified. In this case, the command "
271  "is executed for all instances defined in CVMFS_REPOSITORIES but"
272  " this list is empty. Did you mean running \n\n"
273  " cvmfs_talk -i <repository name> <command>\n");
274  }
275  } else {
276  bool retval = SendCommand(command, instance_info);
277  if (!retval) retcode = 1;
278  }
279  return retcode;
280 }
bool DeterminePaths()
Definition: cvmfs_talk.cc:40
std::string identifier
Definition: cvmfs_talk.cc:92
bool CompleteInfo()
Definition: cvmfs_talk.cc:74
static void Usage(const char *progname)
bool IsOn(const std::string &param_value) const
Definition: options.cc:409
assert((mem||(size==0))&&"Out Of Memory")
void ParseDefault(const std::string &fqrn)
Definition: options.cc:282
int main()
Definition: helper_allow.cc:16
vector< string > SplitString(const string &str, char delim)
Definition: string.cc:290
std::string instance_name
Definition: cvmfs_talk.cc:90
bool GetValue(const std::string &key, std::string *value) const
Definition: options.cc:376
int ConnectSocket(const std::string &path)
Definition: posix.cc:427
std::string workspace
Definition: cvmfs_talk.cc:91
PathString GetParentPath(const PathString &path)
Definition: shortstring.cc:15
bool IsDefined()
Definition: cvmfs_talk.cc:23
bool SendCommand(const std::string &command, InstanceInfo instance_info)
Definition: cvmfs_talk.cc:112
void WritePipe(int fd, const void *buf, size_t nbyte)
Definition: posix.cc:501
std::string socket_path
Definition: cvmfs_talk.cc:89
static bool ReadResponse(int fd)
Definition: cvmfs_talk.cc:96
static std::string GetDefaultDomain()
Definition: cvmfs_talk.cc:28
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:528