CernVM-FS  2.12.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cmd_transaction.cc
Go to the documentation of this file.
1 
5 #include "cvmfs_config.h"
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 =
32  SplitStringBounded(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(
52  "opening a transaction is unsupported within the ephemeral "
53  "writable shell",
55  }
56  if (options.Has("retry-timeout")) {
57  settings->GetTransaction()->SetTimeout(options.GetInt("retry-timeout"));
58  }
59  if (options.Has("template-from")) {
60  if (!options.Has("template-to"))
61  throw EPublish("invalid parameter combination for templates");
62  settings->GetTransaction()->SetTemplate(
63  options.GetString("template-from"), options.GetString("template-to"));
64  }
65  if (options.Has("template")) {
66  if (options.Has("template-from") || options.Has("template-to"))
67  throw EPublish("invalid parameter combination for templates");
68  std::string templ = options.GetString("template");
69  std::vector<std::string> tokens = SplitString(templ, '=');
70  if (tokens.size() != 2)
71  throw EPublish("invalid syntax for --template parameter: " + templ);
72  settings->GetTransaction()->SetTemplate(tokens[0], tokens[1]);
73  }
74 
75  if (!SwitchCredentials(settings->owner_uid(), settings->owner_gid(),
76  false /* temporarily */))
77  {
78  throw EPublish("No write permission to repository",
80  }
81  FileSystemInfo fs_info = GetFileSystemInfo("/cvmfs");
82  if (fs_info.type == kFsTypeAutofs)
83  throw EPublish("Autofs on /cvmfs has to be disabled");
84 
85  settings->GetTransaction()->SetLeasePath(lease_path);
86 
87 
88  UniquePtr<Publisher> publisher;
89  try {
90  publisher = new Publisher(*settings);
91  if (publisher->whitelist()->IsExpired()) {
92  throw EPublish("Repository whitelist for $name is expired",
94  }
95  } catch (const EPublish &e) {
96  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "%s", e.msg().c_str());
99  {
100  return EINVAL;
101  }
102  return EIO;
103  }
104 
105  double whitelist_valid_s =
106  difftime(publisher->whitelist()->expires(), time(NULL));
107  if (whitelist_valid_s < (12 * 60 * 60)) {
109  "Warning: Repository whitelist stays valid for less than 12 hours!");
110  }
111 
112  int rvi = CallServerHook("transaction_before_hook", fqrn);
113  if (rvi != 0) {
115  "transaction hook failed, not opening a transaction");
116  return rvi;
117  }
118 
119  try {
120  publisher->Transaction();
121  } catch (const EPublish &e) {
122  const char *msg_prefix = "CernVM-FS transaction error: ";
125  msg_prefix, e.msg().c_str());
126  return EEXIST;
127  } else if (e.failure() == EPublish::kFailLeaseBusy) {
129  msg_prefix, e.msg().c_str());
130  return EBUSY;
131  } else if (e.failure() == EPublish::kFailLeaseNoEntry) {
133  msg_prefix, e.msg().c_str());
134  return ENOENT;
135  } else if (e.failure() == EPublish::kFailLeaseNoDir) {
137  msg_prefix, e.msg().c_str());
138  return ENOTDIR;
139  } else if (e.failure() == EPublish::kFailInput) {
141  msg_prefix, e.msg().c_str());
142  return EINVAL;
143  }
144  throw;
145  }
146 
147  publisher->session()->SetKeepAlive(true);
148 
149  rvi = CallServerHook("transaction_after_hook", fqrn);
150  if (rvi != 0) {
152  "post transaction hook failed");
153  return rvi;
154  }
155 
156  return 0;
157 }
158 
159 } // namespace publish
int GetInt(const std::string &key) const
Definition: command.h:133
SettingsPublisher * CreateSettingsPublisher(const std::string &ident, bool needs_managed=false)
Definition: settings.cc:594
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:114
std::string GetString(const std::string &key) const
Definition: command.h:123
EFileSystemTypes type
Definition: posix.h:55
std::string msg() const
Definition: except.h:46
const SettingsPublisher & settings() const
Definition: repository.h:317
const std::vector< Argument > & plain_args() const
Definition: command.h:137
vector< string > SplitString(const string &str, char delim)
Definition: string.cc:290
FileSystemInfo GetFileSystemInfo(const std::string &path)
Definition: posix.cc:180
virtual int Main(const Options &options)
vector< string > SplitStringBounded(unsigned max_chunks, const string &str, char delim)
Definition: string.cc:294
EFailures failure() const
Definition: except.h:45
bool SwitchCredentials(const uid_t uid, const gid_t gid, const bool temporarily)
Definition: posix.cc:761
Publisher(const SettingsPublisher &settings, const bool exists=true)
Definition: repository.cc:594
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:528