CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cmd_transaction.cc
Go to the documentation of this file.
1 
6 #include "cmd_transaction.h"
7 
8 #include <errno.h>
9 
10 #include <ctime>
11 #include <string>
12 #include <vector>
13 
14 #include "publish/cmd_util.h"
15 #include "publish/except.h"
16 #include "publish/repository.h"
17 #include "publish/settings.h"
18 #include "util/logging.h"
19 #include "util/posix.h"
20 #include "util/string.h"
21 #include "whitelist.h"
22 
23 namespace publish {
24 
25 int CmdTransaction::Main(const Options &options) {
26  // Repository name and lease path are submitted as a single argument
27  // for historical reasons
28  std::string fqrn;
29  std::string lease_path;
30  if (!options.plain_args().empty()) {
31  std::vector<std::string> tokens = SplitStringBounded(
32  2, options.plain_args()[0].value_str, '/');
33  fqrn = tokens[0];
34  if (tokens.size() == 2)
35  lease_path = MakeCanonicalPath(tokens[1]);
36  }
37 
38  SettingsBuilder builder;
40  try {
41  settings = builder.CreateSettingsPublisher(fqrn, true /* needs_managed */);
42  } catch (const EPublish &e) {
44  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "CernVM-FS error: %s",
45  e.msg().c_str());
46  return 1;
47  }
48  throw;
49  }
50  if (settings->transaction().in_enter_session()) {
51  throw EPublish("opening a transaction is unsupported within the ephemeral "
52  "writable shell",
54  }
55  if (options.Has("retry-timeout")) {
56  settings->GetTransaction()->SetTimeout(options.GetInt("retry-timeout"));
57  }
58  if (options.Has("template-from")) {
59  if (!options.Has("template-to"))
60  throw EPublish("invalid parameter combination for templates");
61  settings->GetTransaction()->SetTemplate(options.GetString("template-from"),
62  options.GetString("template-to"));
63  }
64  if (options.Has("template")) {
65  if (options.Has("template-from") || options.Has("template-to"))
66  throw EPublish("invalid parameter combination for templates");
67  std::string templ = options.GetString("template");
68  std::vector<std::string> tokens = SplitString(templ, '=');
69  if (tokens.size() != 2)
70  throw EPublish("invalid syntax for --template parameter: " + templ);
71  settings->GetTransaction()->SetTemplate(tokens[0], tokens[1]);
72  }
73 
74  if (!SwitchCredentials(settings->owner_uid(), settings->owner_gid(),
75  false /* temporarily */)) {
76  throw EPublish("No write permission to repository",
78  }
79  FileSystemInfo fs_info = GetFileSystemInfo("/cvmfs");
80  if (fs_info.type == kFsTypeAutofs)
81  throw EPublish("Autofs on /cvmfs has to be disabled");
82 
83  settings->GetTransaction()->SetLeasePath(lease_path);
84 
85 
86  UniquePtr<Publisher> publisher;
87  try {
88  publisher = new Publisher(*settings);
89  if (publisher->whitelist()->IsExpired()) {
90  throw EPublish("Repository whitelist for $name is expired",
92  }
93  } catch (const EPublish &e) {
94  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "%s", e.msg().c_str());
97  return EINVAL;
98  }
99  return EIO;
100  }
101 
102  double whitelist_valid_s = difftime(publisher->whitelist()->expires(),
103  time(NULL));
104  if (whitelist_valid_s < (12 * 60 * 60)) {
105  LogCvmfs(
107  "Warning: Repository whitelist stays valid for less than 12 hours!");
108  }
109 
110  int rvi = CallServerHook("transaction_before_hook", fqrn);
111  if (rvi != 0) {
113  "transaction hook failed, not opening a transaction");
114  return rvi;
115  }
116 
117  try {
118  publisher->Transaction();
119  } catch (const EPublish &e) {
120  const char *msg_prefix = "CernVM-FS transaction error: ";
122  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "%s%s", msg_prefix,
123  e.msg().c_str());
124  return EEXIST;
125  } else if (e.failure() == EPublish::kFailLeaseBusy) {
126  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "%s%s", msg_prefix,
127  e.msg().c_str());
128  return EBUSY;
129  } else if (e.failure() == EPublish::kFailLeaseNoEntry) {
130  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "%s%s", msg_prefix,
131  e.msg().c_str());
132  return ENOENT;
133  } else if (e.failure() == EPublish::kFailLeaseNoDir) {
134  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "%s%s", msg_prefix,
135  e.msg().c_str());
136  return ENOTDIR;
137  } else if (e.failure() == EPublish::kFailInput) {
138  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "%s%s", msg_prefix,
139  e.msg().c_str());
140  return EINVAL;
141  }
142  throw;
143  }
144 
145  publisher->session()->SetKeepAlive(true);
146 
147  rvi = CallServerHook("transaction_after_hook", fqrn);
148  if (rvi != 0) {
150  "post transaction hook failed");
151  return rvi;
152  }
153 
154  return 0;
155 }
156 
157 } // namespace publish
int GetInt(const std::string &key) const
Definition: command.h:124
SettingsPublisher * CreateSettingsPublisher(const std::string &ident, bool needs_managed=false)
Definition: settings.cc:572
int CallServerHook(const std::string &func, const std::string &fqrn, const std::string &path_hooks="/etc/cvmfs/cvmfs_server_hooks.sh")
Definition: cmd_util.cc:18
bool Has(const std::string &key) const
Definition: command.h:108
std::string GetString(const std::string &key) const
Definition: command.h:115
EFileSystemTypes type
Definition: posix.h:55
std::string msg() const
Definition: except.h:45
const SettingsPublisher & settings() const
Definition: repository.h:316
const std::vector< Argument > & plain_args() const
Definition: command.h:128
vector< string > SplitString(const string &str, char delim)
Definition: string.cc:306
FileSystemInfo GetFileSystemInfo(const std::string &path)
Definition: posix.cc:179
virtual int Main(const Options &options)
vector< string > SplitStringBounded(unsigned max_chunks, const string &str, char delim)
Definition: string.cc:310
EFailures failure() const
Definition: except.h:44
bool SwitchCredentials(const uid_t uid, const gid_t gid, const bool temporarily)
Definition: posix.cc:773
Publisher(const SettingsPublisher &settings, const bool exists=true)
Definition: repository.cc:619
std::string MakeCanonicalPath(const std::string &path)
Definition: posix.cc:98
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:545