GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/receiver/commit_processor.cc Lines: 0 104 0.0 %
Date: 2019-02-03 02:48:13 Branches: 0 41 0.0 %

Line Branch Exec Source
1
/**
2
 * This file is part of the CernVM File System.
3
 */
4
5
#include "commit_processor.h"
6
7
#include <vector>
8
9
#include "catalog_diff_tool.h"
10
#include "catalog_merge_tool.h"
11
#include "catalog_mgr_ro.h"
12
#include "catalog_mgr_rw.h"
13
#include "compression.h"
14
#include "download.h"
15
#include "logging.h"
16
#include "manifest.h"
17
#include "manifest_fetch.h"
18
#include "params.h"
19
#include "signing_tool.h"
20
#include "statistics.h"
21
#include "swissknife.h"
22
#include "swissknife_history.h"
23
#include "util/algorithm.h"
24
#include "util/pointer.h"
25
#include "util/posix.h"
26
#include "util/raii_temp_dir.h"
27
#include "util/string.h"
28
29
namespace {
30
31
PathString RemoveRepoName(const PathString& lease_path) {
32
  std::string abs_path = lease_path.ToString();
33
  std::string::const_iterator it =
34
      std::find(abs_path.begin(), abs_path.end(), '/');
35
  if (it != abs_path.end()) {
36
    size_t idx = it - abs_path.begin() + 1;
37
    return lease_path.Suffix(idx);
38
  } else {
39
    return lease_path;
40
  }
41
}
42
43
bool CreateNewTag(const RepositoryTag& repo_tag, const std::string& repo_name,
44
                  const receiver::Params& params, const std::string& temp_dir,
45
                  const std::string& manifest_path,
46
                  const std::string& public_key_path) {
47
  swissknife::ArgumentList args;
48
  args['r'].Reset(new std::string(params.spooler_configuration));
49
  args['w'].Reset(new std::string(params.stratum0));
50
  args['t'].Reset(new std::string(temp_dir));
51
  args['m'].Reset(new std::string(manifest_path));
52
  args['p'].Reset(new std::string(public_key_path));
53
  args['f'].Reset(new std::string(repo_name));
54
  args['e'].Reset(new std::string(params.hash_alg_str));
55
  args['a'].Reset(new std::string(repo_tag.name_));
56
  args['c'].Reset(new std::string(repo_tag.channel_));
57
  args['D'].Reset(new std::string(repo_tag.description_));
58
  args['x'].Reset(new std::string());
59
60
  UniquePtr<swissknife::CommandEditTag> edit_cmd(
61
      new swissknife::CommandEditTag());
62
  const int ret = edit_cmd->Main(args);
63
64
  if (ret) {
65
    LogCvmfs(kLogReceiver, kLogSyslogErr, "Error %d creating tag: %s", ret,
66
             repo_tag.name_.c_str());
67
    return false;
68
  }
69
70
  return true;
71
}
72
73
}  // namespace
74
75
namespace receiver {
76
77
CommitProcessor::CommitProcessor() : num_errors_(0) {}
78
79
CommitProcessor::~CommitProcessor() {}
80
81
/**
82
 * Applies the changes from the new catalog onto the repository.
83
 *
84
 * Let:
85
 *   + C_O = the root catalog of the repository (given by old_root_hash) at
86
 *           the beginning of the lease, on the release manager machine
87
 *   + C_N = the root catalog of the repository (given by new_root_hash), on
88
 *           the release manager machine, with the changes introduced during the
89
 *           lease
90
 *   + C_G = the current root catalog of the repository on the gateway machine.
91
 *
92
 * This method applies all the changes from C_N, with respect to C_O, onto C_G.
93
 * The resulting catalog on the gateway machine (C_GN) is then set as root
94
 * catalog in the repository manifest. The method also signes the updated
95
 * repository manifest.
96
 */
97
CommitProcessor::Result CommitProcessor::Process(
98
    const std::string& lease_path, const shash::Any& old_root_hash,
99
    const shash::Any& new_root_hash, const RepositoryTag& tag) {
100
  RepositoryTag final_tag = tag;
101
  // If tag_name is a generic tag, update the time stamp
102
  if (HasPrefix(final_tag.name_, "generic-", false)) {
103
    // timestamp=$(date -u "+%Y-%m-%dT%H:%M:%SZ")
104
    char buf[32];
105
    time_t now = time(NULL);
106
    struct tm timestamp;
107
    gmtime_r(&now, &timestamp);
108
    strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", &timestamp);
109
    final_tag.name_ = std::string("generic-") + buf;
110
  }
111
112
  LogCvmfs(kLogReceiver, kLogSyslog,
113
           "CommitProcessor - lease_path: %s, old hash: %s, new hash: %s, "
114
           "tag_name: %s, tag_channel: %s, tag_description: %s",
115
           lease_path.c_str(), old_root_hash.ToString(true).c_str(),
116
           new_root_hash.ToString(true).c_str(), final_tag.name_.c_str(),
117
           final_tag.channel_.c_str(), final_tag.description_.c_str());
118
119
  const std::vector<std::string> lease_path_tokens =
120
      SplitString(lease_path, '/');
121
122
  const std::string repo_name = lease_path_tokens.front();
123
124
  Params params;
125
  if (!GetParamsFromFile(repo_name, &params)) {
126
    LogCvmfs(
127
        kLogReceiver, kLogSyslogErr,
128
        "CommitProcessor - error: Could not get configuration parameters.");
129
    return kError;
130
  }
131
132
  UniquePtr<ServerTool> server_tool(new ServerTool());
133
134
  if (!server_tool->InitDownloadManager(true)) {
135
    LogCvmfs(
136
        kLogReceiver, kLogSyslogErr,
137
        "CommitProcessor - error: Could not initialize the download manager");
138
    return kError;
139
  }
140
141
  const std::string public_key = "/etc/cvmfs/keys/" + repo_name + ".pub";
142
  const std::string trusted_certs =
143
      "/etc/cvmfs/repositories.d/" + repo_name + "/trusted_certs";
144
  if (!server_tool->InitVerifyingSignatureManager(public_key, trusted_certs)) {
145
    LogCvmfs(
146
        kLogReceiver, kLogSyslogErr,
147
        "CommitProcessor - error: Could not initialize the signature manager");
148
    return kError;
149
  }
150
151
  shash::Any manifest_base_hash;
152
  UniquePtr<manifest::Manifest> manifest(server_tool->FetchRemoteManifest(
153
      params.stratum0, repo_name, manifest_base_hash));
154
155
  // Current catalog from the gateway machine
156
  if (!manifest.IsValid()) {
157
    LogCvmfs(kLogReceiver, kLogSyslogErr,
158
             "CommitProcessor - error: Could not open repository manifest");
159
    return kError;
160
  }
161
162
  LogCvmfs(kLogReceiver, kLogSyslog,
163
           "CommitProcessor - lease_path: %s, target root hash: %s",
164
           lease_path.c_str(),
165
           manifest->catalog_hash().ToString(false).c_str());
166
167
  const std::string spooler_temp_dir =
168
      GetSpoolerTempDir(params.spooler_configuration);
169
  assert(!spooler_temp_dir.empty());
170
  assert(MkdirDeep(spooler_temp_dir + "/receiver", 0666, true));
171
  const std::string temp_dir_root =
172
      spooler_temp_dir + "/receiver/commit_processor";
173
174
  const PathString relative_lease_path = RemoveRepoName(PathString(lease_path));
175
176
  LogCvmfs(kLogReceiver, kLogSyslog,
177
           "CommitProcessor - lease_path: %s, merging catalogs",
178
           lease_path.c_str());
179
180
  CatalogMergeTool<catalog::WritableCatalogManager,
181
                   catalog::SimpleCatalogManager>
182
      merge_tool(params.stratum0, old_root_hash, new_root_hash,
183
                 relative_lease_path, temp_dir_root,
184
                 server_tool->download_manager(), manifest.weak_ref());
185
  if (!merge_tool.Init()) {
186
    LogCvmfs(kLogReceiver, kLogSyslogErr,
187
             "Error: Could not initialize the catalog merge tool");
188
    return kError;
189
  }
190
191
  std::string new_manifest_path;
192
  if (!merge_tool.Run(params, &new_manifest_path)) {
193
    LogCvmfs(kLogReceiver, kLogSyslogErr,
194
             "CommitProcessor - error: Catalog merge failed");
195
    return kMergeFailure;
196
  }
197
198
  UniquePtr<RaiiTempDir> raii_temp_dir(RaiiTempDir::Create(temp_dir_root));
199
  const std::string temp_dir = raii_temp_dir->dir();
200
  const std::string certificate = "/etc/cvmfs/keys/" + repo_name + ".crt";
201
  const std::string private_key = "/etc/cvmfs/keys/" + repo_name + ".key";
202
203
  if (!CreateNewTag(final_tag, repo_name, params, temp_dir, new_manifest_path,
204
                    public_key)) {
205
    LogCvmfs(kLogReceiver, kLogSyslogErr, "Error creating tag: %s",
206
             final_tag.name_.c_str());
207
    return kError;
208
  }
209
210
  // We need to re-initialize the ServerTool component for signing
211
  server_tool.Destroy();
212
  server_tool = new ServerTool();
213
214
  LogCvmfs(kLogReceiver, kLogSyslog,
215
           "CommitProcessor - lease_path: %s, signing manifest",
216
           lease_path.c_str());
217
218
  SigningTool signing_tool(server_tool.weak_ref());
219
  SigningTool::Result res = signing_tool.Run(
220
      new_manifest_path, params.stratum0, params.spooler_configuration,
221
      temp_dir, certificate, private_key, repo_name, "", "",
222
      "/var/spool/cvmfs/" + repo_name + "/reflog.chksum");
223
  switch (res) {
224
    case SigningTool::kReflogChecksumMissing:
225
      LogCvmfs(kLogReceiver, kLogSyslogErr,
226
               "CommitProcessor - error: missing reflog.chksum");
227
      return kMissingReflog;
228
    case SigningTool::kReflogMissing:
229
      LogCvmfs(kLogReceiver, kLogSyslogErr,
230
               "CommitProcessor - error: missing reflog");
231
      return kMissingReflog;
232
    case SigningTool::kError:
233
    case SigningTool::kInitError:
234
      LogCvmfs(kLogReceiver, kLogSyslogErr,
235
               "CommitProcessor - error: signing manifest");
236
      return kError;
237
    case SigningTool::kSuccess:
238
      LogCvmfs(kLogReceiver, kLogSyslog,
239
               "CommitProcessor - lease_path: %s, success.",
240
               lease_path.c_str());
241
  }
242
243
  {
244
    UniquePtr<ServerTool> server_tool(new ServerTool());
245
246
    if (!server_tool->InitDownloadManager(true)) {
247
      LogCvmfs(
248
          kLogReceiver, kLogSyslogErr,
249
          "CommitProcessor - error: Could not initialize the download manager");
250
      return kError;
251
    }
252
253
    const std::string public_key = "/etc/cvmfs/keys/" + repo_name + ".pub";
254
    const std::string trusted_certs =
255
        "/etc/cvmfs/repositories.d/" + repo_name + "/trusted_certs";
256
    if (!server_tool->InitVerifyingSignatureManager(public_key,
257
                                                    trusted_certs)) {
258
      LogCvmfs(kLogReceiver, kLogSyslogErr,
259
               "CommitProcessor - error: Could not initialize the signature "
260
               "manager");
261
      return kError;
262
    }
263
264
    shash::Any manifest_base_hash;
265
    UniquePtr<manifest::Manifest> manifest(server_tool->FetchRemoteManifest(
266
        params.stratum0, repo_name, manifest_base_hash));
267
268
    LogCvmfs(kLogReceiver, kLogSyslog,
269
             "CommitProcessor - lease_path: %s, new root hash: %s",
270
             lease_path.c_str(),
271
             manifest->catalog_hash().ToString(false).c_str());
272
  }
273
274
  return kSuccess;
275
}
276
277
}  // namespace receiver