GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/publish/settings.h
Date: 2026-08-30 02:40:36
Exec Total Coverage
Lines: 0 166 0.0%
Branches: 0 120 0.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_PUBLISH_SETTINGS_H_
6 #define CVMFS_PUBLISH_SETTINGS_H_
7
8 #include <stdint.h>
9 #include <unistd.h>
10
11 #include <map>
12 #include <string>
13
14 #include "compression/compression.h"
15 #include "crypto/hash.h"
16 #include "sync_union.h"
17 #include "upload_spooler_definition.h"
18
19 class OptionsManager;
20
21 namespace publish {
22
23 /**
24 * Allows for settings that remember whether they have been explicitly
25 * overwritten. Otherwise, default values can be changed to upstream repository
26 * settings.
27 */
28 template<class T>
29 class Setting {
30 public:
31 Setting() : value_(), is_default_(true) { }
32 explicit Setting(const T &v) : value_(v), is_default_(true) { }
33
34 Setting &operator=(const T &v) {
35 value_ = v;
36 is_default_ = false;
37 return *this;
38 }
39
40 const T &operator()() const { return value_; }
41
42 bool SetIfDefault(const T &v) {
43 if (!is_default_)
44 return false;
45 value_ = v;
46 is_default_ = false;
47 return true;
48 }
49
50 bool is_default() const { return is_default_; }
51
52 T *GetPtr() { return &value_; }
53
54 private:
55 T value_;
56 bool is_default_;
57 }; // Setting
58
59
60 /**
61 * Steers the aggressiveness of Publisher::ManagedNode::Check()
62 */
63 enum EUnionMountRepairMode {
64 kUnionMountRepairNever = 0,
65 kUnionMountRepairSafe,
66 kUnionMountRepairAlways
67 };
68
69
70 // Settings from the point of construction always represent a valid
71 // configuration. The constructor sets default values, which can be overwritten
72 // by setters. The setters throw errors when invalid options are detected.
73
74 class SettingsSpoolArea {
75 public:
76 explicit SettingsSpoolArea(const std::string &fqrn)
77 : workspace_(std::string("/var/spool/cvmfs/") + fqrn)
78 , tmp_dir_(workspace_() + "/tmp")
79 , union_mnt_(std::string("/cvmfs/") + fqrn)
80 , repair_mode_(kUnionMountRepairSafe) { }
81
82 void UseSystemTempDir();
83 void SetSpoolArea(const std::string &path);
84 void SetUnionMount(const std::string &path);
85 void SetRepairMode(const EUnionMountRepairMode val);
86
87 // Creates, if necessary, all the directories in the spool area and the temp
88 // directory. Does not take care of the union mount point.
89 void EnsureDirectories();
90
91 std::string workspace() const { return workspace_(); }
92 std::string tmp_dir() const { return tmp_dir_(); }
93 std::string readonly_mnt() const { return workspace_() + "/rdonly"; }
94 std::string readonly_talk_socket() const {
95 return workspace_() + "/cvmfs_io";
96 }
97 std::string union_mnt() const { return union_mnt_(); }
98 std::string scratch_base() const { return workspace_() + "/scratch"; }
99 std::string scratch_dir() const { return scratch_base() + "/current"; }
100 std::string scratch_wastebin() const { return scratch_base() + "/wastebin"; }
101 std::string log_dir() const { return workspace() + "/logs"; }
102 // TODO(jblomer): shouldn't this be in /etc/cvmfs/repository.../client.conf
103 std::string client_config() const { return workspace_() + "/client.config"; }
104 std::string client_lconfig() const { return workspace_() + "/client.local"; }
105 std::string client_log() const { return log_dir() + "/cvmfs.log"; }
106 std::string cache_dir() const { return workspace_() + "/cache"; }
107 std::string ovl_work_dir() const { return workspace_() + "/ovl_work"; }
108 std::string checkout_marker() const { return workspace_() + "/checkout"; }
109 std::string gw_session_token() const {
110 return workspace_() + "/session_token";
111 }
112 std::string transaction_lock() const {
113 return workspace_() + "/in_transaction.lock";
114 }
115 std::string publishing_lock() const {
116 return workspace_() + "/is_publishing.lock";
117 }
118 EUnionMountRepairMode repair_mode() const { return repair_mode_(); }
119
120 private:
121 Setting<std::string> workspace_;
122 Setting<std::string> tmp_dir_;
123 Setting<std::string> union_mnt_;
124 /**
125 * How aggressively should the mount point stack be repaired
126 */
127 Setting<EUnionMountRepairMode> repair_mode_;
128 }; // SettingsSpoolArea
129
130
131 class SettingsTransaction {
132 public:
133 explicit SettingsTransaction(const std::string &fqrn)
134 : layout_revision_(0)
135 , in_enter_session_(false)
136 , hash_algorithm_(shash::kShake128)
137 , compression_algorithm_(zlib::kZlibDefault)
138 , ttl_second_(240)
139 , is_garbage_collectable_(true)
140 , is_volatile_(false)
141 , enforce_limits_(false)
142 // SyncParameters::kDefaultNestedKcatalogLimit
143 , limit_nested_catalog_kentries_(500)
144 // SyncParameters::kDefaultRootKcatalogLimit
145 , limit_root_catalog_kentries_(500)
146 // SyncParameters::kDefaultFileMbyteLimit
147 , limit_file_size_mb_(1024)
148 , use_catalog_autobalance_(false)
149 // SyncParameters::kDefaultMaxWeight
150 , autobalance_max_weight_(100000)
151 // SyncParameters::kDefaultMinWeight
152 , autobalance_min_weight_(1000)
153 , print_changeset_(false)
154 , dry_run_(false)
155 , allow_nonexistent_path_(false)
156 , union_fs_(kUnionFsUnknown)
157 , timeout_s_(0)
158 , spool_area_(fqrn) { }
159
160 void SetLayoutRevision(const unsigned revision);
161 void SetInEnterSession(const bool value);
162 void SetBaseHash(const shash::Any &hash);
163 void SetUnionFsType(const std::string &union_fs);
164 void SetHashAlgorithm(const std::string &algorithm);
165 void SetCompressionAlgorithm(const std::string &algorithm);
166 void SetEnforceLimits(bool value);
167 void SetEnableMtimeNs(bool value);
168 void SetLimitNestedCatalogKentries(unsigned value);
169 void SetLimitRootCatalogKentries(unsigned value);
170 void SetLimitFileSizeMb(unsigned value);
171 void SetUseCatalogAutobalance(bool value);
172 void SetAutobalanceMaxWeight(unsigned value);
173 void SetAutobalanceMinWeight(unsigned value);
174 void SetPrintChangeset(bool value);
175 void SetDryRun(bool value);
176 void SetAllowNonexistentPath(bool value);
177 void SetTimeout(unsigned seconds);
178 void SetLeasePath(const std::string &path);
179 void SetTemplate(const std::string &from, const std::string &to);
180 void DetectUnionFsType();
181
182 /**
183 * 0 - wait infinitely
184 * <0: unset, fail immediately
185 */
186 int GetTimeoutS() const;
187
188 unsigned layout_revision() const { return layout_revision_(); }
189 bool in_enter_session() const { return in_enter_session_(); }
190 shash::Any base_hash() const { return base_hash_(); }
191 shash::Algorithms hash_algorithm() const { return hash_algorithm_(); }
192 zlib::Algorithms compression_algorithm() const {
193 return compression_algorithm_();
194 }
195 uint32_t ttl_second() const { return ttl_second_(); }
196 bool is_garbage_collectable() const { return is_garbage_collectable_(); }
197 bool is_volatile() const { return is_volatile_(); }
198 bool enforce_limits() const { return enforce_limits_(); }
199 bool enable_mtime_ns() const { return enable_mtime_ns_(); }
200 unsigned limit_nested_catalog_kentries() const {
201 return limit_nested_catalog_kentries_();
202 }
203 unsigned limit_root_catalog_kentries() const {
204 return limit_root_catalog_kentries_();
205 }
206 unsigned limit_file_size_mb() const { return limit_file_size_mb_(); }
207 bool use_catalog_autobalance() const { return use_catalog_autobalance_(); }
208 unsigned autobalance_max_weight() const { return autobalance_max_weight_(); }
209 unsigned autobalance_min_weight() const { return autobalance_min_weight_(); }
210 bool print_changeset() const { return print_changeset_(); }
211 bool dry_run() const { return dry_run_(); }
212 bool allow_nonexistent_path() const { return allow_nonexistent_path_(); }
213 std::string voms_authz() const { return voms_authz_(); }
214 UnionFsType union_fs() const { return union_fs_(); }
215 std::string lease_path() const { return lease_path_(); }
216 std::string template_from() const { return template_from_(); }
217 std::string template_to() const { return template_to_(); }
218
219 const SettingsSpoolArea &spool_area() const { return spool_area_; }
220 SettingsSpoolArea *GetSpoolArea() { return &spool_area_; }
221
222 bool HasTemplate() const { return !template_to().empty(); }
223
224 private:
225 bool ValidateUnionFs();
226
227 /**
228 * See CVMFS_CREATOR_VERSION
229 */
230 Setting<unsigned> layout_revision_;
231 /**
232 * Set to true if the settings have been created from the environment of
233 * the ephemeral writable shell (cvmfs_server enter command).
234 */
235 Setting<bool> in_enter_session_;
236 /**
237 * The root catalog hash based on which the transaction takes place.
238 * Usually the current root catalog from the manifest, which should be equal
239 * to the root hash of the mounted read-only volume. In some cases, this
240 * can be different though, e.g. for checked out branches or after silent
241 * transactions such as template transactions.
242 */
243 Setting<shash::Any> base_hash_;
244 Setting<shash::Algorithms> hash_algorithm_;
245 Setting<zlib::Algorithms> compression_algorithm_;
246 Setting<uint32_t> ttl_second_;
247 Setting<bool> is_garbage_collectable_;
248 Setting<bool> is_volatile_;
249 Setting<bool> enforce_limits_;
250 Setting<bool> enable_mtime_ns_;
251 Setting<unsigned> limit_nested_catalog_kentries_;
252 Setting<unsigned> limit_root_catalog_kentries_;
253 Setting<unsigned> limit_file_size_mb_;
254 Setting<bool> use_catalog_autobalance_;
255 Setting<unsigned> autobalance_max_weight_;
256 Setting<unsigned> autobalance_min_weight_;
257 Setting<bool> print_changeset_;
258 Setting<bool> dry_run_;
259 /**
260 * Permit opening a transaction on a gateway lease path whose parent
261 * directory does not exist yet. The missing ancestor directories are
262 * materialized by the receiver during the commit's catalog merge.
263 */
264 Setting<bool> allow_nonexistent_path_;
265 Setting<std::string> voms_authz_;
266 Setting<UnionFsType> union_fs_;
267 /**
268 * How long to retry taking a lease before giving up
269 */
270 Setting<unsigned> timeout_s_;
271 Setting<std::string> lease_path_;
272 /**
273 * Used for template transactions where a directory tree gets cloned
274 * (from --> to) as part of opening the transaction
275 */
276 Setting<std::string> template_from_;
277 Setting<std::string> template_to_;
278
279 SettingsSpoolArea spool_area_;
280 }; // class SettingsTransaction
281
282
283 class SettingsGc { }; // class SettingsGc
284
285
286 class SettingsStorage {
287 public:
288 explicit SettingsStorage(const std::string &fqrn)
289 : fqrn_(fqrn)
290 , type_(upload::SpoolerDefinition::Local)
291 , tmp_dir_(std::string("/srv/cvmfs/") + fqrn + "/data/txn")
292 , endpoint_(std::string("/srv/cvmfs/") + fqrn) { }
293
294 std::string GetLocator() const;
295 void SetLocator(const std::string &locator);
296 void MakeLocal(const std::string &path);
297 void MakeS3(const std::string &s3_config, const std::string &tmp_dir);
298 void MakeGateway(const std::string &host, unsigned port,
299 const std::string &tmp_dir);
300
301 upload::SpoolerDefinition::DriverType type() const { return type_(); }
302 std::string endpoint() const { return endpoint_(); }
303
304 private:
305 Setting<std::string> fqrn_;
306 Setting<upload::SpoolerDefinition::DriverType> type_;
307 Setting<std::string> tmp_dir_;
308 Setting<std::string> endpoint_;
309 }; // class SettingsStorage
310
311
312 class SettingsKeychain {
313 public:
314 explicit SettingsKeychain(const std::string &fqrn)
315 : fqrn_(fqrn)
316 , keychain_dir_("/etc/cvmfs/keys")
317 , master_private_key_path_(keychain_dir_() + "/" + fqrn + ".masterkey")
318 , master_public_key_path_(keychain_dir_() + "/" + fqrn + ".pub")
319 , private_key_path_(keychain_dir_() + "/" + fqrn + ".key")
320 , certificate_path_(keychain_dir_() + "/" + fqrn + ".crt")
321 , gw_key_path_(keychain_dir_() + "/" + fqrn + ".gw") { }
322
323 void SetKeychainDir(const std::string &keychain_dir);
324
325 bool HasDanglingMasterKeys() const;
326 bool HasMasterKeys() const;
327 bool HasDanglingRepositoryKeys() const;
328 bool HasRepositoryKeys() const;
329 bool HasGatewayKey() const;
330
331 std::string keychain_dir() const { return keychain_dir_(); }
332 std::string master_private_key_path() const {
333 return master_private_key_path_();
334 }
335 std::string master_public_key_path() const {
336 return master_public_key_path_();
337 }
338 std::string private_key_path() const { return private_key_path_(); }
339 std::string certificate_path() const { return certificate_path_(); }
340 std::string gw_key_path() const { return gw_key_path_(); }
341
342 private:
343 Setting<std::string> fqrn_;
344 Setting<std::string> keychain_dir_;
345 Setting<std::string> master_private_key_path_;
346 Setting<std::string> master_public_key_path_;
347 Setting<std::string> private_key_path_;
348 Setting<std::string> certificate_path_;
349 Setting<std::string> gw_key_path_;
350 }; // class SettingsKeychain
351
352
353 class SettingsPublisher;
354 class SettingsReplica;
355
356 /**
357 * Description of a read-only repository
358 */
359 class SettingsRepository {
360 public:
361 explicit SettingsRepository(const std::string &fqrn)
362 : fqrn_(fqrn)
363 , url_(std::string("http://localhost/cvmfs/") + fqrn_())
364 , proxy_("")
365 , tmp_dir_("/tmp")
366 , keychain_(fqrn) { }
367 explicit SettingsRepository(const SettingsPublisher &settings_publisher);
368 explicit SettingsRepository(const SettingsReplica &settings_replica);
369
370 void SetUrl(const std::string &url);
371 void SetProxy(const std::string &proxy);
372 void SetTmpDir(const std::string &tmp_dir);
373 void SetCertBundle(const std::string &cert_bundle);
374
375 std::string fqrn() const { return fqrn_(); }
376 std::string url() const { return url_(); }
377 std::string proxy() const { return proxy_(); }
378 std::string tmp_dir() const { return tmp_dir_(); }
379 std::string cert_bundle() const { return cert_bundle_(); }
380
381 const SettingsKeychain &keychain() const { return keychain_; }
382 SettingsKeychain *GetKeychain() { return &keychain_; }
383
384 private:
385 Setting<std::string> fqrn_;
386 Setting<std::string> url_;
387 Setting<std::string> proxy_;
388 Setting<std::string> tmp_dir_;
389 // Currently only used for testing, steered by X509_CERT_BUNDLE
390 // in /etc/cvmfs/server.local
391 Setting<std::string> cert_bundle_;
392
393 SettingsKeychain keychain_;
394 }; // class SettingsRepository
395
396
397 /**
398 * Description of an editable repository.
399 */
400 class SettingsPublisher {
401 public:
402 static const unsigned kDefaultWhitelistValidity; // 30 days
403
404 explicit SettingsPublisher(const std::string &fqrn)
405 : fqrn_(fqrn)
406 , url_(std::string("http://localhost/cvmfs/") + fqrn)
407 , proxy_("")
408 , owner_uid_(0)
409 , owner_gid_(0)
410 , whitelist_validity_days_(kDefaultWhitelistValidity)
411 , is_silent_(false)
412 , is_managed_(false)
413 , ignore_invalid_lease_(false)
414 , storage_(fqrn_())
415 , transaction_(fqrn_())
416 , keychain_(fqrn_()) { }
417 explicit SettingsPublisher(const SettingsRepository &settings_repository);
418
419 void SetUrl(const std::string &url);
420 void SetProxy(const std::string &proxy);
421 void SetOwner(const std::string &user_name);
422 void SetOwner(uid_t uid, gid_t gid);
423 void SetIsSilent(bool value);
424 void SetIsManaged(bool value);
425 void SetIgnoreInvalidLease(bool value);
426
427 std::string GetReadOnlyXAttr(const std::string &attr);
428
429 std::string fqrn() const { return fqrn_(); }
430 std::string url() const { return url_(); }
431 std::string proxy() const { return proxy_(); }
432 unsigned whitelist_validity_days() const {
433 return whitelist_validity_days_();
434 }
435 uid_t owner_uid() const { return owner_uid_(); }
436 uid_t owner_gid() const { return owner_gid_(); }
437 bool is_silent() const { return is_silent_(); }
438 bool is_managed() const { return is_managed_(); }
439 bool ignore_invalid_lease() const { return ignore_invalid_lease_(); }
440
441 const SettingsStorage &storage() const { return storage_; }
442 const SettingsTransaction &transaction() const { return transaction_; }
443 const SettingsKeychain &keychain() const { return keychain_; }
444 SettingsStorage *GetStorage() { return &storage_; }
445 SettingsTransaction *GetTransaction() { return &transaction_; }
446 SettingsKeychain *GetKeychain() { return &keychain_; }
447
448 private:
449 Setting<std::string> fqrn_;
450 Setting<std::string> url_;
451 Setting<std::string> proxy_;
452 Setting<uid_t> owner_uid_;
453 Setting<gid_t> owner_gid_;
454 Setting<unsigned> whitelist_validity_days_;
455 Setting<bool> is_silent_;
456 Setting<bool> is_managed_;
457 // When trying to drop the session, ignore an invalid lease failure. Useful
458 // to recover a publisher with abort -f.
459 Setting<bool> ignore_invalid_lease_;
460
461 SettingsStorage storage_;
462 SettingsTransaction transaction_;
463 SettingsKeychain keychain_;
464 }; // SettingsPublisher
465
466
467 /**
468 * Description of a stratum 1
469 */
470 class SettingsReplica {
471 public:
472 explicit SettingsReplica(const std::string &fqrn)
473 : fqrn_(fqrn)
474 , alias_(fqrn)
475 , url_(std::string("http://localhost/cvmfs/") + alias_()) { }
476
477 std::string fqrn() const { return fqrn_(); }
478 std::string url() const { return url_(); }
479
480 private:
481 Setting<std::string> fqrn_;
482 Setting<std::string> alias_;
483 Setting<std::string> url_;
484 }; // class SettingsReplica
485
486
487 /**
488 * Create Settings objects from the system configuration in
489 * /etc/cvmfs/repositories.d
490 */
491 class SettingsBuilder : SingleCopy {
492 public:
493 SettingsBuilder()
494 : config_path_("/etc/cvmfs/repositories.d"), options_mgr_(NULL) { }
495 ~SettingsBuilder();
496 /**
497 * Used in unit tests.
498 */
499 explicit SettingsBuilder(const std::string &c) : config_path_(c) { }
500
501 /**
502 * If ident is a url, creates a generic settings object inferring the fqrn
503 * from the url.
504 * Otherwise, looks in the config files in /etc/cvmfs/repositories.d/<alias>/
505 * If alias is an empty string, the command still succeeds iff there is a
506 * single repository under /etc/cvmfs/repositories.d
507 */
508 SettingsRepository CreateSettingsRepository(const std::string &ident);
509
510 /**
511 * If ident is a url, creates a generic settings object inferring the fqrn
512 * from the url.
513 * Otherwise, looks in the config files in /etc/cvmfs/repositories.d/<alias>/
514 * If alias is an empty string, the command still succeeds iff there is a
515 * single repository under /etc/cvmfs/repositories.d
516 * If needs_managed is true, remote repositories are rejected
517 * In an "enter environment" (see cmd_enter), the spool area of the enter
518 * environment is applied.
519 */
520
521 SettingsPublisher *CreateSettingsPublisher(const std::string &ident,
522 bool needs_managed = false);
523
524 OptionsManager *options_mgr() const { return options_mgr_; }
525 bool IsManagedRepository() const { return options_mgr_ != NULL; }
526
527 /**
528 * Get the values from the server configuration and set them to the publisher
529 * settings.
530 */
531 void ApplyOptionsFromServerPath(const OptionsManager &options_mgr_,
532 SettingsPublisher *settings_publisher);
533
534 void SetConfigPath(const std::string &config_path) {
535 config_path_ = config_path;
536 }
537
538 private:
539 /**
540 * For non locally managed repositories, a configuration file should be
541 * provided in order to publish from the ephemeral shell through the gateway
542 */
543 std::string config_path_;
544
545 /**
546 * For locally managed repositories, the options manager is non NULL and
547 * contains the configuration after a call to CreateSettingsRepository()
548 */
549 OptionsManager *options_mgr_;
550 // TODO(avalenzu): options_mgr_ should become a unique pointer.
551
552 /**
553 * Returns the name of the one and only repository under kConfigPath
554 * Throws an exception if there are none or multiple repositories.
555 * The alias is usually the fqrn except for a replica with an explicit
556 * alias set different from the fqrn (e.g. if Stratum 0 and 1 are hosted)
557 * on the same node.
558 */
559 std::string GetSingleAlias();
560
561 /**
562 * If in a ephemeral writable shell, parse $session_dir/env.conf
563 * Otherwise return an empty map. A non-empty map has at least CVMFS_FQRN set.
564 */
565 std::map<std::string, std::string> GetSessionEnvironment();
566
567 /**
568 * Create settings from an ephermal writable shell
569 */
570 SettingsPublisher *CreateSettingsPublisherFromSession();
571 }; // class SettingsBuilder
572
573 } // namespace publish
574
575 #endif // CVMFS_PUBLISH_SETTINGS_H_
576