CernVM-FS  2.9.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 "logging.h"
15 #include "publish/cmd_util.h"
16 #include "publish/except.h"
17 #include "publish/repository.h"
18 #include "publish/settings.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  SplitString(options.plain_args()[0].value_str, '/', 2);
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) {
98  {
99  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "%s", e.msg().c_str());
100  return EINVAL;
101  }
102  }
103 
104  double whitelist_valid_s =
105  difftime(publisher->whitelist()->expires(), time(NULL));
106  if (whitelist_valid_s < (12 * 60 * 60)) {
108  "Warning: Repository whitelist stays valid for less than 12 hours!");
109  }
110 
111  int rvi = CallServerHook("transaction_before_hook", fqrn);
112  if (rvi != 0) {
114  "transaction hook failed, not opening a transaction");
115  return rvi;
116  }
117 
118  try {
119  publisher->Transaction();
120  } catch (const EPublish &e) {
121  const char *msg_prefix = "CernVM-FS transaction error: ";
124  msg_prefix, e.msg().c_str());
125  return EEXIST;
126  } else if (e.failure() == EPublish::kFailLeaseBusy) {
128  msg_prefix, e.msg().c_str());
129  return EBUSY;
130  } else if (e.failure() == EPublish::kFailLeaseNoEntry) {
132  msg_prefix, e.msg().c_str());
133  return ENOENT;
134  } else if (e.failure() == EPublish::kFailLeaseNoDir) {
136  msg_prefix, e.msg().c_str());
137  return ENOTDIR;
138  } else if (e.failure() == EPublish::kFailInput) {
140  msg_prefix, e.msg().c_str());
141  return EINVAL;
142  }
143  throw;
144  }
145 
146  publisher->session()->SetKeepAlive(true);
147 
148  rvi = CallServerHook("transaction_after_hook", fqrn);
149  if (rvi != 0) {
151  "post transaction hook failed");
152  return rvi;
153  }
154 
155  return 0;
156 }
157 
158 } // namespace publish
#define LogCvmfs(source, mask,...)
Definition: logging.h:20
int GetInt(const std::string &key) const
Definition: command.h:133
SettingsPublisher * CreateSettingsPublisher(const std::string &ident, bool needs_managed=false)
Definition: settings.cc:508
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
vector< string > SplitString(const string &str, const char delim, const unsigned max_chunks)
Definition: string.cc:288
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:51
std::string msg() const
Definition: except.h:46
const SettingsPublisher & settings() const
Definition: repository.h:306
const std::vector< Argument > & plain_args() const
Definition: command.h:137
FileSystemInfo GetFileSystemInfo(const std::string &path)
Definition: posix.cc:216
virtual int Main(const Options &options)
Publisher(const SettingsPublisher &settings)
Definition: repository.cc:628
EFailures failure() const
Definition: except.h:45
bool SwitchCredentials(const uid_t uid, const gid_t gid, const bool temporarily)
Definition: posix.cc:786
std::string MakeCanonicalPath(const std::string &path)
Definition: posix.cc:96