CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
repository.cc
Go to the documentation of this file.
1 
6 #include "publish/repository.h"
7 
8 #include <cassert>
9 #include <cstddef>
10 #include <cstdlib>
11 
12 #include "catalog_mgr_ro.h"
13 #include "catalog_mgr_rw.h"
14 #include "crypto/hash.h"
15 #include "crypto/signature.h"
16 #include "gateway_util.h"
17 #include "history_sqlite.h"
19 #include "manifest.h"
20 #include "manifest_fetch.h"
21 #include "network/download.h"
22 #include "publish/except.h"
24 #include "publish/settings.h"
25 #include "reflog.h"
26 #include "statistics.h"
27 #include "sync_mediator.h"
28 #include "sync_union_aufs.h"
29 #include "sync_union_overlayfs.h"
30 #include "sync_union_tarball.h"
31 #include "upload.h"
33 #include "util/logging.h"
34 #include "util/pointer.h"
35 #include "whitelist.h"
36 
37 // TODO(jblomer): Remove Me
38 namespace swissknife {
39 class CommandTag {
40  static const std::string kHeadTag;
41  static const std::string kPreviousHeadTag;
42 };
43 const std::string CommandTag::kHeadTag = "trunk";
44 const std::string CommandTag::kPreviousHeadTag = "trunk-previous";
45 } // namespace swissknife
46 
47 namespace publish {
48 
50  : settings_(settings)
51  , statistics_(new perf::Statistics())
52  , signature_mgr_(new signature::SignatureManager())
53  , download_mgr_(NULL)
54  , simple_catalog_mgr_(NULL)
55  , whitelist_(NULL)
56  , reflog_(NULL)
57  , manifest_(NULL)
58  , history_(NULL) {
60 
61  if (exists) {
62  int rvb;
63  const std::string keys = JoinStrings(
64  FindFilesBySuffix(settings.keychain().keychain_dir(), ".pub"), ":");
65  rvb = signature_mgr_->LoadPublicRsaKeys(keys);
66  if (!rvb) {
68  delete signature_mgr_;
69  delete statistics_;
70  throw EPublish("cannot load public rsa key");
71  }
72  }
73 
74  if (!settings.cert_bundle().empty()) {
75  const int rvi = setenv("X509_CERT_BUNDLE", settings.cert_bundle().c_str(),
76  1 /* overwrite */);
77  if (rvi != 0)
78  throw EPublish("cannot set X509_CERT_BUNDLE environment variable");
79  }
81  16, perf::StatisticsTemplate("download", statistics_));
83 
84  if (settings.proxy() != "") {
85  download_mgr_->SetProxyChain(settings.proxy(), "",
87  }
88 
89  if (exists) {
90  try {
91  DownloadRootObjects(settings.url(), settings.fqrn(), settings.tmp_dir());
92  } catch (const EPublish &e) {
94  delete signature_mgr_;
95  delete download_mgr_;
96  delete statistics_;
97  throw;
98  }
99  }
100 }
101 
103  if (signature_mgr_ != NULL)
104  signature_mgr_->Fini();
105 
106  delete history_;
107  delete manifest_;
108  delete reflog_;
109  delete whitelist_;
110  delete signature_mgr_;
111  delete download_mgr_;
112  delete simple_catalog_mgr_;
113  delete statistics_;
114 }
115 
116 const history::History *Repository::history() const { return history_; }
117 
119  if (simple_catalog_mgr_ != NULL)
120  return simple_catalog_mgr_;
121 
124  settings_.url(),
125  settings_.tmp_dir(),
127  statistics_,
128  true /* manage_catalog_files */);
130  return simple_catalog_mgr_;
131 }
132 
133 
134 void Repository::DownloadRootObjects(const std::string &url,
135  const std::string &fqrn,
136  const std::string &tmp_dir) {
137  delete whitelist_;
139  const whitelist::Failures rv_whitelist = whitelist_->LoadUrl(url);
141  throw EPublish(std::string("cannot load whitelist [")
142  + whitelist::Code2Ascii(rv_whitelist) + "]");
143  }
144 
146  const uint64_t minimum_timestamp = 0;
147  const shash::Any *base_catalog = NULL;
148  const manifest::Failures rv_manifest =
149  manifest::Fetch(url, fqrn, minimum_timestamp, base_catalog,
150  signature_mgr_, download_mgr_, &ensemble);
151  if (rv_manifest != manifest::kFailOk)
152  throw EPublish("cannot load manifest");
153  delete manifest_;
154  manifest_ = new manifest::Manifest(*ensemble.manifest);
155 
156  std::string reflog_path;
157  FILE *reflog_fd = CreateTempFile(tmp_dir + "/reflog", kPrivateFileMode, "w",
158  &reflog_path);
159  const std::string reflog_url = url + "/.cvmfsreflog";
160  // TODO(jblomer): verify reflog hash
161  // shash::Any reflog_hash(manifest_->GetHashAlgorithm());
162  cvmfs::FileSink filesink(reflog_fd);
163  download::JobInfo download_reflog(&reflog_url, false /* compressed */,
164  false /* probe hosts */, NULL, &filesink);
165  download::Failures rv_dl = download_mgr_->Fetch(&download_reflog);
166  fclose(reflog_fd);
167  if (rv_dl == download::kFailOk) {
168  delete reflog_;
169  reflog_ = manifest::Reflog::Open(reflog_path);
170  if (reflog_ == NULL)
171  throw EPublish("cannot open reflog");
173  } else {
174  if (!download_reflog.IsFileNotFound()) {
175  throw EPublish(std::string("cannot load reflog [")
176  + download::Code2Ascii(rv_dl) + "]");
177  }
178  assert(reflog_ == NULL);
179  }
180 
181  std::string tags_path;
182  FILE *tags_fd = CreateTempFile(tmp_dir + "/tags", kPrivateFileMode, "w",
183  &tags_path);
184  if (!manifest_->history().IsNull()) {
185  const std::string tags_url =
186  url + "/data/" + manifest_->history().MakePath();
187  const shash::Any tags_hash(manifest_->history());
188  cvmfs::FileSink filesink(tags_fd);
189  download::JobInfo download_tags(&tags_url, true /* compressed */,
190  true /* probe hosts */, &tags_hash,
191  &filesink);
192  rv_dl = download_mgr_->Fetch(&download_tags);
193  fclose(tags_fd);
194  if (rv_dl != download::kFailOk)
195  throw EPublish("cannot load tag database");
196  delete history_;
198  if (history_ == NULL)
199  throw EPublish("cannot open tag database");
200  } else {
201  fclose(tags_fd);
202  delete history_;
203  history_ = history::SqliteHistory::Create(tags_path, fqrn);
204  if (history_ == NULL)
205  throw EPublish("cannot create tag database");
206  }
208 
209  if (!manifest_->meta_info().IsNull()) {
210  const shash::Any info_hash(manifest_->meta_info());
211  const std::string info_url = url + "/data/" + info_hash.MakePath();
212  cvmfs::MemSink metainfo_memsink;
213  download::JobInfo download_info(&info_url, true /* compressed */,
214  true /* probe_hosts */, &info_hash,
215  &metainfo_memsink);
216  const download::Failures rv_info = download_mgr_->Fetch(&download_info);
217  if (rv_info != download::kFailOk) {
218  throw EPublish(std::string("cannot load meta info [")
219  + download::Code2Ascii(rv_info) + "]");
220  }
221  meta_info_ = std::string(reinterpret_cast<char *>(metainfo_memsink.data()),
222  metainfo_memsink.pos());
223  } else {
224  meta_info_ = "n/a";
225  }
226 }
227 
228 
229 std::string Repository::GetFqrnFromUrl(const std::string &url) {
230  return GetFileName(MakeCanonicalPath(url));
231 }
232 
233 
235  const std::string url = settings_.url() + "/.cvmfs_master_replica";
236  download::JobInfo head(&url, false /* probe_hosts */);
237  const download::Failures retval = download_mgr_->Fetch(&head);
238  if (retval == download::kFailOk) {
239  return true;
240  }
241  if (head.IsFileNotFound()) {
242  return false;
243  }
244 
245  throw EPublish(std::string("error looking for .cvmfs_master_replica [")
246  + download::Code2Ascii(retval) + "]");
247 }
248 
249 
250 //------------------------------------------------------------------------------
251 
252 
254  if ((spooler_files_ != NULL) && (spooler_catalogs_ != NULL))
255  return;
256  assert((spooler_files_ == NULL) && (spooler_catalogs_ == NULL));
257 
258  upload::SpoolerDefinition sd(settings_.storage().GetLocator(),
259  settings_.transaction().hash_algorithm(),
260  settings_.transaction().compression_algorithm());
261  sd.session_token_file = settings_.transaction()
262  .spool_area()
263  .gw_session_token();
264  sd.key_file = settings_.keychain().gw_key_path();
265 
266  spooler_files_ = upload::Spooler::Construct(sd,
268  if (spooler_files_ == NULL)
269  throw EPublish("could not initialize file spooler");
270 
271  const upload::SpoolerDefinition sd_catalogs(sd.Dup2DefaultCompression());
272  spooler_catalogs_ = upload::Spooler::Construct(
273  sd_catalogs, statistics_publish_.weak_ref());
274  if (spooler_catalogs_ == NULL) {
275  delete spooler_files_;
276  throw EPublish("could not initialize catalog spooler");
277  }
278 }
279 
280 
283  throw EPublish("dangling master key pair");
284  }
286  throw EPublish("dangling repository keys");
287  }
292 
294  const std::string whitelist_str = whitelist::Whitelist::CreateString(
295  settings_.fqrn(), settings_.whitelist_validity_days(),
296  settings_.transaction().hash_algorithm(), signature_mgr_);
297  const whitelist::Failures rv_wl = whitelist_->LoadMem(whitelist_str);
298  if (rv_wl != whitelist::kFailOk)
299  throw EPublish("whitelist generation failed");
300 }
301 
302 
304  // Reflog
305  const std::string reflog_path = CreateTempPath(
306  settings_.transaction().spool_area().tmp_dir() + "/cvmfs_reflog", 0600);
308  if (reflog_ == NULL)
309  throw EPublish("could not create reflog");
310  reflog_->TakeDatabaseFileOwnership();
311 
312  // Root file catalog and initial manifest
314  settings_.transaction().spool_area().tmp_dir(),
315  settings_.transaction().is_volatile(),
316  settings_.transaction().voms_authz(),
318  spooler_catalogs_->WaitForUpload();
319  if (manifest_ == NULL)
320  throw EPublish("could not create initial file catalog");
321  reflog_->AddCatalog(manifest_->catalog_hash());
322 
324  manifest_->set_ttl(settings_.transaction().ttl_second());
325  const bool
326  needs_bootstrap_shortcuts = !settings_.transaction().voms_authz().empty();
327  manifest_->set_has_alt_catalog_path(needs_bootstrap_shortcuts);
329  settings_.transaction().is_garbage_collectable());
330 
331  // Tag database
332  const std::string tags_path = CreateTempPath(
333  settings_.transaction().spool_area().tmp_dir() + "/cvmfs_tags", 0600);
335  if (history_ == NULL)
336  throw EPublish("could not create tag database");
337  history_->TakeDatabaseFileOwnership();
338  const history::History::Tag tag_trunk(
340  manifest_->revision(), manifest_->publish_timestamp(), "empty repository",
341  "" /* branch */);
342  history_->Insert(tag_trunk);
343 
344  // Meta information, TODO(jblomer)
345  meta_info_ = "{}";
346 }
347 
348 
351  if (!spooler_files_->Create())
352  throw EPublish("could not initialize repository storage area");
353 }
354 
355 
357  upload::Spooler::CallbackPtr callback = spooler_files_->RegisterListener(
359  spooler_files_->ProcessCertificate(
361  spooler_files_->WaitForUpload();
362  spooler_files_->UnregisterListener(callback);
363 }
364 
365 
367  assert(history_ != NULL);
369  const string history_path = history_->filename();
371  delete history_;
372 
373  upload::Spooler::CallbackPtr callback = spooler_files_->RegisterListener(
375  spooler_files_->ProcessHistory(history_path);
376  spooler_files_->WaitForUpload();
377  spooler_files_->UnregisterListener(callback);
378 
380  assert(history_ != NULL);
382 }
383 
384 
386  upload::Spooler::CallbackPtr callback = spooler_files_->RegisterListener(
388  spooler_files_->ProcessMetainfo(new StringIngestionSource(meta_info_));
389  spooler_files_->WaitForUpload();
390  spooler_files_->UnregisterListener(callback);
391 }
392 
393 
395  std::string signed_manifest = manifest_->ExportString();
396  shash::Any manifest_hash(settings_.transaction().hash_algorithm());
398  reinterpret_cast<const unsigned char *>(signed_manifest.data()),
399  signed_manifest.length(), &manifest_hash);
400  signed_manifest += "--\n" + manifest_hash.ToString() + "\n";
401  unsigned char *signature;
402  unsigned sig_size;
403  bool rvb = signature_mgr_->Sign(
404  reinterpret_cast<const unsigned char *>(manifest_hash.ToString().data()),
405  manifest_hash.GetHexSize(), &signature, &sig_size);
406  if (!rvb)
407  throw EPublish("cannot sign manifest");
408  signed_manifest += std::string(reinterpret_cast<char *>(signature), sig_size);
409  free(signature);
410 
411  // Create alternative bootstrapping symlinks for VOMS secured repos
413  rvb = spooler_files_->PlaceBootstrappingShortcut(manifest_->certificate())
414  && spooler_files_->PlaceBootstrappingShortcut(
416  && (manifest_->history().IsNull()
417  || spooler_files_->PlaceBootstrappingShortcut(
418  manifest_->history()))
419  && (manifest_->meta_info().IsNull()
420  || spooler_files_->PlaceBootstrappingShortcut(
421  manifest_->meta_info()));
422  if (!rvb)
423  EPublish("cannot place VOMS bootstrapping symlinks");
424  }
425 
426  upload::Spooler::CallbackPtr callback = spooler_files_->RegisterListener(
428  spooler_files_->Upload(".cvmfspublished",
429  new StringIngestionSource(signed_manifest));
430  spooler_files_->WaitForUpload();
431  spooler_files_->UnregisterListener(callback);
432 }
433 
434 
436  const string reflog_path = reflog_->database_file();
438  delete reflog_;
439 
440  shash::Any hash_reflog(settings_.transaction().hash_algorithm());
441  manifest::Reflog::HashDatabase(reflog_path, &hash_reflog);
442 
443  upload::Spooler::CallbackPtr callback = spooler_files_->RegisterListener(
445  spooler_files_->UploadReflog(reflog_path);
446  spooler_files_->WaitForUpload();
447  spooler_files_->UnregisterListener(callback);
448 
449  manifest_->set_reflog_hash(hash_reflog);
450 
451  reflog_ = manifest::Reflog::Open(reflog_path);
452  assert(reflog_ != NULL);
454 }
455 
456 
458  // TODO(jblomer): PKCS7 handling
459  upload::Spooler::CallbackPtr callback = spooler_files_->RegisterListener(
461  spooler_files_->Upload(".cvmfswhitelist",
463  spooler_files_->WaitForUpload();
464  spooler_files_->UnregisterListener(callback);
465 }
466 
467 
468 Publisher *Publisher::Create(const SettingsPublisher &settings) {
469  UniquePtr<Publisher> publisher(new Publisher(settings, false));
470 
471  LogCvmfs(kLogCvmfs, publisher->llvl_ | kLogStdout | kLogNoLinebreak,
472  "Creating Key Chain... ");
473  publisher->CreateKeychain();
474  publisher->ExportKeychain();
475  LogCvmfs(kLogCvmfs, publisher->llvl_ | kLogStdout, "done");
476 
477  LogCvmfs(kLogCvmfs, publisher->llvl_ | kLogStdout | kLogNoLinebreak,
478  "Creating Backend Storage... ");
479  publisher->CreateStorage();
480  publisher->PushWhitelist();
481  LogCvmfs(kLogCvmfs, publisher->llvl_ | kLogStdout, "done");
482 
483  LogCvmfs(kLogCvmfs, publisher->llvl_ | kLogStdout | kLogNoLinebreak,
484  "Creating Initial Repository... ");
485  publisher->InitSpoolArea();
486  publisher->CreateRootObjects();
487  publisher->PushHistory();
488  publisher->PushCertificate();
489  publisher->PushMetainfo();
490  publisher->PushReflog();
491  publisher->PushManifest();
492  // TODO(jblomer): meta-info
493 
494  // Re-create from empty repository in order to properly initialize
495  // parent Repository object
496  publisher = new Publisher(settings);
497 
498  LogCvmfs(kLogCvmfs, publisher->llvl_ | kLogStdout, "done");
499 
500  return publisher.Release();
501 }
502 
505 
506  bool rvb;
509  if (!rvb)
510  throw EPublish("cannot export public master key");
513  if (!rvb)
514  throw EPublish("cannot export certificate");
515 
518  if (!rvb)
519  throw EPublish("cannot export private certificate key");
522  if (!rvb)
523  throw EPublish("cannot export private master key");
524 
525  int rvi;
526  rvi = chown(settings_.keychain().master_public_key_path().c_str(),
527  settings_.owner_uid(), settings_.owner_gid());
528  if (rvi != 0)
529  throw EPublish("cannot set key file ownership");
530  rvi = chown(settings_.keychain().certificate_path().c_str(),
531  settings_.owner_uid(), settings_.owner_gid());
532  if (rvi != 0)
533  throw EPublish("cannot set key file ownership");
534  rvi = chown(settings_.keychain().private_key_path().c_str(),
535  settings_.owner_uid(), settings_.owner_gid());
536  if (rvi != 0)
537  throw EPublish("cannot set key file ownership");
538  rvi = chown(settings_.keychain().master_private_key_path().c_str(),
539  settings_.owner_uid(), settings_.owner_gid());
540  if (rvi != 0)
541  throw EPublish("cannot set key file ownership");
542 }
543 
545  if (result.return_code != 0) {
546  throw EPublish("cannot write certificate to storage");
547  }
550 }
551 
553  if (result.return_code != 0) {
554  throw EPublish("cannot write tag database to storage");
555  }
558 }
559 
561  if (result.return_code != 0) {
562  throw EPublish("cannot write repository meta info to storage");
563  }
566 }
567 
569  if (result.return_code != 0) {
570  throw EPublish("cannot write manifest to storage");
571  }
572 }
573 
575  if (result.return_code != 0) {
576  throw EPublish("cannot write reflog to storage");
577  }
578 }
579 
581  if (result.return_code != 0) {
582  throw EPublish("cannot write whitelist to storage");
583  }
584 }
585 
586 void Publisher::CreateDirectoryAsOwner(const std::string &path, int mode) {
587  const bool rvb = MkdirDeep(path, mode);
588  if (!rvb)
589  throw EPublish("cannot create directory " + path);
590  const int rvi =
591  chown(path.c_str(), settings_.owner_uid(), settings_.owner_gid());
592  if (rvi != 0)
593  throw EPublish("cannot set ownership on directory " + path);
594 }
595 
597  CreateDirectoryAsOwner(settings_.transaction().spool_area().workspace(),
599  CreateDirectoryAsOwner(settings_.transaction().spool_area().tmp_dir(),
601  CreateDirectoryAsOwner(settings_.transaction().spool_area().cache_dir(),
603  CreateDirectoryAsOwner(settings_.transaction().spool_area().scratch_dir(),
605  CreateDirectoryAsOwner(settings_.transaction().spool_area().ovl_work_dir(),
607 
608  // On a managed node, the mount points are already mounted
609  if (!DirectoryExists(settings_.transaction().spool_area().readonly_mnt())) {
610  CreateDirectoryAsOwner(settings_.transaction().spool_area().readonly_mnt(),
612  }
613  if (!DirectoryExists(settings_.transaction().spool_area().union_mnt())) {
614  CreateDirectoryAsOwner(settings_.transaction().spool_area().union_mnt(),
616  }
617 }
618 
619 Publisher::Publisher(const SettingsPublisher &settings, const bool exists)
620  : Repository(SettingsRepository(settings), exists)
621  , settings_(settings)
622  , statistics_publish_(new perf::StatisticsTemplate("publish", statistics_))
623  , llvl_(settings.is_silent() ? kLogNone : kLogNormal)
624  , in_transaction_(settings.transaction().spool_area().transaction_lock())
625  , is_publishing_(settings.transaction().spool_area().publishing_lock())
626  , spooler_files_(NULL)
627  , spooler_catalogs_(NULL)
628  , catalog_mgr_(NULL)
629  , sync_parameters_(NULL)
630  , sync_mediator_(NULL)
631  , sync_union_(NULL) {
633  const unsigned layout_revision = settings.transaction().layout_revision();
634  throw EPublish("This repository uses layout revision "
635  + StringifyInt(layout_revision)
636  + ".\n"
637  "This version of CernVM-FS requires layout revision "
639  + ", which is\n"
640  "incompatible to "
641  + StringifyInt(layout_revision)
642  + ".\n\n"
643  "Please run `cvmfs_server migrate` to update your "
644  "repository before "
645  "proceeding.",
647  }
648 
649  if (!exists)
650  return;
651 
652  CreateDirectoryAsOwner(settings_.transaction().spool_area().tmp_dir(),
654 
655  if (settings.storage().type() == upload::SpoolerDefinition::Gateway) {
656  if (!settings.keychain().HasGatewayKey()) {
657  throw EPublish("gateway key missing: "
658  + settings.keychain().gw_key_path());
659  }
661  if (!gw_key_.IsValid()) {
662  throw EPublish("cannot read gateway key: "
663  + settings.keychain().gw_key_path());
664  }
665  }
666 
667  if ((settings.storage().type() != upload::SpoolerDefinition::Gateway)
668  && !settings.transaction().in_enter_session()) {
670  settings.keychain().certificate_path());
671  if (!rvb)
672  throw EPublish("cannot load certificate, thus cannot commit changes");
674  settings.keychain().private_key_path(), "");
675  if (!rvb)
676  throw EPublish("cannot load private key, thus cannot commit changes");
677  // The private master key might be on a key card instead
678  if (FileExists(settings.keychain().master_private_key_path())) {
680  settings.keychain().master_private_key_path());
681  if (!rvb)
682  throw EPublish("cannot load private master key");
683  }
684  if (!signature_mgr_->KeysMatch())
685  throw EPublish("corrupted keychain");
686  }
687 
688  if (settings.is_managed())
689  managed_node_ = new ManagedNode(this);
691  if (in_transaction_.IsSet())
693 }
694 
696  delete sync_union_;
697  delete sync_mediator_;
698  delete sync_parameters_;
699  delete catalog_mgr_;
700  delete spooler_catalogs_;
701  delete spooler_files_;
702 }
703 
704 
707 
708  if (catalog_mgr_ == NULL) {
710  settings_.transaction().base_hash(),
711  settings_.url(),
712  settings_.transaction().spool_area().tmp_dir(),
715  settings_.transaction().enforce_limits(),
716  settings_.transaction().limit_nested_catalog_kentries(),
717  settings_.transaction().limit_root_catalog_kentries(),
718  settings_.transaction().limit_file_size_mb(),
719  statistics_,
720  settings_.transaction().use_catalog_autobalance(),
721  settings_.transaction().autobalance_max_weight(),
722  settings_.transaction().autobalance_min_weight(),
723  "");
724  catalog_mgr_->Init();
725  }
726 
727  if (sync_parameters_ == NULL) {
728  SyncParameters *p = new SyncParameters();
729  p->spooler = spooler_files_;
730  p->repo_name = settings_.fqrn();
731  p->dir_union = settings_.transaction().spool_area().union_mnt();
732  p->dir_scratch = settings_.transaction().spool_area().scratch_dir();
733  p->dir_rdonly = settings_.transaction().spool_area().readonly_mnt();
734  p->dir_temp = settings_.transaction().spool_area().tmp_dir();
735  p->base_hash = settings_.transaction().base_hash();
736  p->stratum0 = settings_.url();
737  // p->manifest_path = SHOULD NOT BE NEEDED
738  // p->spooler_definition = SHOULD NOT BE NEEDED;
739  // p->union_fs_type = SHOULD NOT BE NEEDED
740  p->print_changeset = settings_.transaction().print_changeset();
741  p->dry_run = settings_.transaction().dry_run();
742  sync_parameters_ = p;
743  }
744 
745  if (sync_mediator_ == NULL) {
748  }
749 
750  if (sync_union_ == NULL) {
751  switch (settings_.transaction().union_fs()) {
752  case kUnionFsAufs:
755  settings_.transaction().spool_area().readonly_mnt(),
756  settings_.transaction().spool_area().union_mnt(),
757  settings_.transaction().spool_area().scratch_dir());
758  break;
759  case kUnionFsOverlay:
762  settings_.transaction().spool_area().readonly_mnt(),
763  settings_.transaction().spool_area().union_mnt(),
764  settings_.transaction().spool_area().scratch_dir());
765  break;
766  case kUnionFsTarball:
769  settings_.transaction().spool_area().readonly_mnt(),
770  // TODO(jblomer): get from settings
771  "tar_file",
772  "base_directory",
773  -1u,
774  -1u,
775  "to_delete",
776  false /* create_catalog */);
777  break;
778  default:
779  throw EPublish("unknown union file system");
780  }
781  const bool rvb = sync_union_->Initialize();
782  if (!rvb) {
783  delete sync_union_;
784  sync_union_ = NULL;
785  throw EPublish("cannot initialize union file system engine");
786  }
787  }
788 }
789 
791  const std::string session_dir = Env::GetEnterSessionDir();
792  const std::string session_pid_tmp = session_dir + "/session_pid";
793  std::string session_pid;
794  const int fd_session_pid = open(session_pid_tmp.c_str(), O_RDONLY);
795  if (fd_session_pid < 0)
796  throw EPublish("Session pid cannot be retrieved");
797  SafeReadToString(fd_session_pid, &session_pid);
798 
799  const pid_t pid_child = String2Uint64(session_pid);
800  kill(pid_child, SIGUSR1);
801 }
802 
805 
807 
809  bool rvb = sync_mediator_->Commit(manifest_);
810  if (!rvb)
811  throw EPublish("cannot write change set to storage");
812 
813  if (!settings_.transaction().dry_run()) {
814  spooler_files_->WaitForUpload();
815  spooler_catalogs_->WaitForUpload();
816  spooler_files_->FinalizeSession(false /* commit */);
817 
818  const std::string old_root_hash = settings_.transaction()
819  .base_hash()
820  .ToString(true /* with_suffix */);
821  const std::string new_root_hash = manifest_->catalog_hash().ToString(
822  true /* with_suffix */);
823  rvb = spooler_catalogs_->FinalizeSession(
824  true /* commit */, old_root_hash, new_root_hash,
825  /* TODO(jblomer) */ sync_parameters_->repo_tag);
826  if (!rvb)
827  throw EPublish("failed to commit transaction");
828 
829  // Reset to the new catalog root hash
830  settings_.GetTransaction()->SetBaseHash(manifest_->catalog_hash());
831  // TODO(jblomer): think about how to deal with the scratch area at
832  // this point
833  // WipeScratchArea();
834  }
835 
836  delete sync_union_;
837  delete sync_mediator_;
838  delete sync_parameters_;
839  delete catalog_mgr_;
840  sync_union_ = NULL;
841  sync_mediator_ = NULL;
842  sync_parameters_ = NULL;
843  catalog_mgr_ = NULL;
844 
845  if (!settings_.transaction().dry_run()) {
846  LogCvmfs(kLogCvmfs, kLogStdout, "New revision: %" PRIu64,
847  manifest_->revision());
849  }
850 }
851 
853  if (!in_transaction_.IsSet())
854  throw EPublish("cannot publish outside transaction");
855 
856  PushReflog();
857  PushManifest();
859 }
860 
861 
862 void Publisher::MarkReplicatible(bool value) {
864 
865  if (value) {
866  spooler_files_->Upload("/dev/null", "/.cvmfs_master_replica");
867  } else {
868  spooler_files_->RemoveAsync("/.cvmfs_master_replica");
869  }
870  spooler_files_->WaitForUpload();
871  if (spooler_files_->GetNumberOfErrors() > 0)
872  throw EPublish("cannot set replication mode");
873 }
874 
876 void Publisher::Migrate() { }
878 void Publisher::Rollback() { }
880 
881 void Publisher::Transaction() {
883  session()->SetKeepAlive(true);
884 }
885 
886 //------------------------------------------------------------------------------
887 
888 
890  : Repository(SettingsRepository(settings)) { }
891 
892 
894 
895 } // namespace publish
bool Commit(manifest::Manifest *manifest)
int return_code
the return value of the spooler operation
void set_repository_name(const std::string &repository_name)
Definition: manifest.h:98
void TakeDatabaseFileOwnership()
Definition: reflog.cc:294
const SettingsRepository settings_
Definition: repository.h:136
std::string database_file() const
Definition: reflog.cc:322
void CreateRootObjects()
Definition: repository.cc:303
manifest::Reflog * reflog_
Definition: repository.h:146
bool IsNull() const
Definition: hash.h:371
download::DownloadManager * download_mgr_
Definition: repository.h:140
bool HasGatewayKey() const
Definition: settings.cc:264
std::string stratum0
bool AddHistory(const shash::Any &history)
Definition: reflog.cc:135
void ConstructSyncManagers()
Definition: repository.cc:705
void OnUploadReflog(const upload::SpoolerResult &result)
Definition: repository.cc:574
catalog::SimpleCatalogManager * GetSimpleCatalogManager()
Definition: repository.cc:118
UniquePtr< ManagedNode > managed_node_
Definition: repository.h:380
Session * session() const
Definition: repository.h:319
NameString GetFileName(const PathString &path)
Definition: shortstring.cc:28
const int kPrivateDirMode
Definition: posix.h:36
T * weak_ref() const
Definition: pointer.h:46
void Ingest()
Definition: repository.cc:875
UniquePtr< perf::StatisticsTemplate > statistics_publish_
Definition: repository.h:364
static Publisher * Create(const SettingsPublisher &settings)
unsigned char * data()
Definition: sink_mem.h:115
std::string keychain_dir() const
Definition: settings.h:322
std::string GetCertificate() const
Definition: signature.cc:417
static const std::string kPreviousHeadTag
Definition: repository.cc:41
Failures LoadUrl(const std::string &base_url)
Definition: whitelist.cc:214
std::string gw_key_path() const
Definition: settings.h:331
FILE * CreateTempFile(const std::string &path_prefix, const int mode, const char *open_flags, std::string *final_path)
Definition: posix.cc:1014
string JoinStrings(const vector< string > &strings, const string &joint)
Definition: string.cc:356
std::string ToString(const bool with_suffix=false) const
Definition: hash.h:241
void OnProcessCertificate(const upload::SpoolerResult &result)
Definition: repository.cc:544
virtual bool Initialize()
Definition: sync_union.cc:24
void set_certificate(const shash::Any &certificate)
Definition: manifest.h:94
const history::History * history() const
void CreateDirectoryAsOwner(const std::string &path, int mode)
Definition: repository.cc:586
void PushCertificate()
Definition: repository.cc:356
unsigned layout_revision() const
Definition: settings.h:186
void SetProxyChain(const std::string &proxy_list, const std::string &fallback_proxy_list, const ProxySetModes set_mode)
Definition: download.cc:2795
void OnUploadWhitelist(const upload::SpoolerResult &result)
Definition: repository.cc:580
void CreateStorage()
Definition: repository.cc:349
bool IsMasterReplica()
Definition: repository.cc:234
std::string private_key_path() const
Definition: settings.h:329
const SettingsPublisher & settings() const
Definition: repository.h:316
perf::Statistics * statistics_
Definition: repository.h:138
Status status() const
Definition: whitelist.h:103
std::string CreateTempPath(const std::string &path_prefix, const int mode)
Definition: posix.cc:1042
void set_meta_info(const shash::Any &meta_info)
Definition: manifest.h:116
std::string GetPrivateKey()
Definition: signature.cc:434
std::string ExportString() const
Definition: manifest.cc:185
virtual ~Replica()
Definition: repository.cc:893
std::string repo_name
assert((mem||(size==0))&&"Out Of Memory")
bool has_alt_catalog_path() const
Definition: manifest.h:131
upload::Spooler * spooler_catalogs_
Definition: repository.h:383
gateway::GatewayKey gw_key_
Definition: repository.h:371
bool SafeWriteToFile(const std::string &content, const std::string &path, int mode)
Definition: posix.cc:2137
void PushMetainfo()
Definition: repository.cc:385
bool LoadPrivateKeyPath(const std::string &file_pem, const std::string &password)
Definition: signature.cc:185
class __attribute__((visibility("default"))) Publisher ManagedNode(Publisher *p)
Definition: repository.h:173
void PushReflog()
Definition: repository.cc:435
uint64_t catalog_size() const
Definition: manifest.h:126
void ExitShell()
Definition: repository.cc:790
bool AddCatalog(const shash::Any &catalog)
Definition: reflog.cc:129
static Reflog * Create(const std::string &database_path, const std::string &repo_name)
Definition: reflog.cc:32
std::string cert_bundle() const
Definition: settings.h:370
catalog::WritableCatalogManager * catalog_mgr_
Definition: repository.h:384
std::string dir_scratch
bool IsFileNotFound()
Definition: jobinfo.cc:33
bool HasMasterKeys() const
Definition: settings.cc:247
void GenerateCertificate(const std::string &cn)
Definition: signature.cc:503
uint64_t revision() const
Definition: manifest.h:122
Repository(const SettingsRepository &settings, const bool exists=true)
Definition: repository.cc:49
static Reflog * Open(const std::string &database_path)
Definition: reflog.cc:17
static SqliteHistory * OpenWritable(const std::string &file_name)
std::string master_public_key_path() const
Definition: settings.h:326
bool FileExists(const std::string &path)
Definition: posix.cc:803
std::string GetActivePubkeys() const
Definition: signature.cc:393
std::string dir_temp
const int kPrivateFileMode
Definition: posix.h:35
void OnProcessMetainfo(const upload::SpoolerResult &result)
Definition: repository.cc:560
const char * Code2Ascii(const Failures error)
static manifest::Manifest * CreateRepository(const std::string &dir_temp, const bool volatile_content, const std::string &voms_authz, upload::Spooler *spooler)
bool HasRepositoryKeys() const
Definition: settings.cc:260
std::string proxy() const
Definition: settings.h:368
std::string meta_info_
Definition: repository.h:150
void PushHistory()
Definition: repository.cc:366
const SettingsKeychain & keychain() const
Definition: settings.h:434
publish::SyncUnion * sync_union_
Definition: repository.h:387
uint64_t publish_timestamp() const
Definition: manifest.h:129
bool AddMetainfo(const shash::Any &metainfo)
Definition: reflog.cc:141
void Transaction()
const int kDefaultDirMode
Definition: posix.h:33
bool Sign(const unsigned char *buffer, const unsigned buffer_size, unsigned char **signature, unsigned *signature_size)
Definition: signature.cc:781
void OnUploadManifest(const upload::SpoolerResult &result)
Definition: repository.cc:568
std::string dir_rdonly
signature::SignatureManager * signature_mgr_
Definition: repository.h:139
void SetKeepAlive(bool value)
Failures Fetch(const std::string &base_url, const std::string &repository_name, const uint64_t minimum_timestamp, const shash::Any *base_catalog, signature::SignatureManager *signature_manager, download::DownloadManager *download_manager, ManifestEnsemble *ensemble)
void UpdateMetaInfo()
Definition: repository.cc:879
std::string master_private_key_path() const
Definition: settings.h:323
void DownloadRootObjects(const std::string &url, const std::string &fqrn, const std::string &tmp_dir)
Definition: repository.cc:134
shash::Any base_hash
static const std::string kHeadTag
Definition: repository.cc:40
shash::Any certificate() const
Definition: manifest.h:127
virtual ~Publisher()
upload::Spooler * spooler
bool MkdirDeep(const std::string &path, const mode_t mode, bool verify_writable)
Definition: posix.cc:855
bool LoadCertificatePath(const std::string &file_pem)
Definition: signature.cc:246
const SettingsTransaction & transaction() const
Definition: settings.h:433
bool IsValid() const
Definition: gateway_util.h:18
const char * Code2Ascii(const Failures error)
Definition: whitelist.h:49
ServerLockFile is_publishing_
Definition: repository.h:370
std::string dir_union
void Sync()
Definition: repository.cc:803
void InitSpoolArea()
Definition: repository.cc:596
static void HashDatabase(const std::string &database_path, shash::Any *hash_reflog)
Definition: reflog.cc:309
void PushManifest()
Definition: repository.cc:394
shash::Any catalog_hash() const
Definition: manifest.h:125
string StringifyInt(const int64_t value)
Definition: string.cc:77
std::string certificate_path() const
Definition: settings.h:330
catalog::SimpleCatalogManager * simple_catalog_mgr_
Definition: repository.h:144
history::SqliteHistory * history_
Definition: repository.h:148
void Resign()
Definition: repository.cc:877
bool is_managed() const
Definition: settings.h:429
void Publish()
const SettingsStorage & storage() const
Definition: settings.h:432
void DropDatabaseFileOwnership()
Definition: reflog.cc:300
bool SetPreviousRevision(const shash::Any &history_hash)
bool LoadPrivateMasterKeyPath(const std::string &file_pem)
Definition: signature.cc:155
bool DirectoryExists(const std::string &path)
Definition: posix.cc:824
UniquePtr< Session > session_
Definition: repository.h:379
void set_history(const shash::Any &history_db)
Definition: manifest.h:97
void set_garbage_collectability(const bool garbage_collectable)
Definition: manifest.h:110
bool AddCertificate(const shash::Any &certificate)
Definition: reflog.cc:122
std::string filename() const
bool SafeReadToString(int fd, std::string *final_result)
Definition: posix.cc:2117
manifest::Manifest * manifest_
Definition: repository.h:147
void OnProcessHistory(const upload::SpoolerResult &result)
Definition: repository.cc:552
void set_ttl(const uint32_t ttl)
Definition: manifest.h:92
void HashMem(const unsigned char *buffer, const unsigned buffer_size, Any *any_digest)
Definition: hash.cc:255
upload::Spooler * spooler_files_
Definition: repository.h:382
void MarkReplicatible(bool value)
Definition: repository.cc:862
size_t pos()
Definition: sink_mem.h:114
class __attribute__((visibility("default"))) Replica Replica(const SettingsReplica &settings)
Definition: repository.cc:889
const SettingsKeychain & keychain() const
Definition: settings.h:372
std::string ExportString() const
Definition: whitelist.cc:75
virtual void Traverse()=0
uint64_t String2Uint64(const string &value)
Definition: string.cc:240
std::string GetPrivateMasterKey()
Definition: signature.cc:452
void Migrate(InodeTracker *old_tracker, glue::InodeTracker *new_tracker)
Definition: compat.cc:79
Failures Fetch(JobInfo *info)
Definition: download.cc:1984
shash::Any history() const
Definition: manifest.h:128
ServerFlagFile in_transaction_
Definition: repository.h:369
static std::string CreateString(const std::string &fqrn, int validity_days, shash::Algorithms hash_algorithm, signature::SignatureManager *signature_manager)
Definition: whitelist.cc:46
bool LoadPublicRsaKeys(const std::string &path_list)
Definition: signature.cc:306
whitelist::Whitelist * whitelist_
Definition: repository.h:145
GatewayKey ReadGatewayKey(const std::string &key_file_name)
Definition: gateway_util.cc:28
static SqliteHistory * Create(const std::string &file_name, const std::string &fqrn)
bool HasDanglingRepositoryKeys() const
Definition: settings.cc:253
Failures LoadMem(const std::string &whitelist)
Definition: whitelist.cc:194
RepositoryTag repo_tag
SyncMediator * sync_mediator_
Definition: repository.h:386
std::string fqrn() const
Definition: settings.h:366
void ExportKeychain()
Definition: repository.cc:503
void set_has_alt_catalog_path(const bool &has_alt_path)
Definition: manifest.h:113
int llvl_
Definition: repository.h:368
upload::SpoolerDefinition::DriverType type() const
Definition: settings.h:292
Publisher(const SettingsPublisher &settings, const bool exists=true)
Definition: repository.cc:619
std::string MakePath() const
Definition: hash.h:306
std::string MakeCanonicalPath(const std::string &path)
Definition: posix.cc:98
bool in_enter_session() const
Definition: settings.h:187
virtual ~Repository()
Definition: repository.cc:102
void set_reflog_hash(const shash::Any &checksum)
Definition: manifest.h:120
std::string url() const
Definition: settings.h:367
void ConstructSpoolers()
Definition: repository.cc:253
void Rollback()
void CreateKeychain()
Definition: repository.cc:281
void PushWhitelist()
Definition: repository.cc:457
std::vector< std::string > FindFilesBySuffix(const std::string &dir, const std::string &suffix)
Definition: posix.cc:1129
shash::Any meta_info() const
Definition: manifest.h:132
std::string tmp_dir() const
Definition: settings.h:369
static const unsigned kRequiredLayoutRevision
Definition: repository.h:277
SyncParameters * sync_parameters_
Definition: repository.h:385
class static __attribute__((visibility("default"))) Repository std::string GetFqrnFromUrl(const std::string &url)
Definition: repository.cc:229
bool HasDanglingMasterKeys() const
Definition: settings.cc:239
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:545