GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/publish/settings.h
Date: 2025-06-22 02:36:02
Exec Total Coverage
Lines: 0 164 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 , union_fs_(kUnionFsUnknown)
156 , timeout_s_(0)
157 , spool_area_(fqrn) { }
158
159 void SetLayoutRevision(const unsigned revision);
160 void SetInEnterSession(const bool value);
161 void SetBaseHash(const shash::Any &hash);
162 void SetUnionFsType(const std::string &union_fs);
163 void SetHashAlgorithm(const std::string &algorithm);
164 void SetCompressionAlgorithm(const std::string &algorithm);
165 void SetEnforceLimits(bool value);
166 void SetEnableMtimeNs(bool value);
167 void SetLimitNestedCatalogKentries(unsigned value);
168 void SetLimitRootCatalogKentries(unsigned value);
169 void SetLimitFileSizeMb(unsigned value);
170 void SetUseCatalogAutobalance(bool value);
171 void SetAutobalanceMaxWeight(unsigned value);
172 void SetAutobalanceMinWeight(unsigned value);
173 void SetPrintChangeset(bool value);
174 void SetDryRun(bool value);
175 void SetTimeout(unsigned seconds);
176 void SetLeasePath(const std::string &path);
177 void SetTemplate(const std::string &from, const std::string &to);
178 void DetectUnionFsType();
179
180 /**
181 * 0 - wait infinitely
182 * <0: unset, fail immediately
183 */
184 int GetTimeoutS() const;
185
186 unsigned layout_revision() const { return layout_revision_(); }
187 bool in_enter_session() const { return in_enter_session_(); }
188 shash::Any base_hash() const { return base_hash_(); }
189 shash::Algorithms hash_algorithm() const { return hash_algorithm_(); }
190 zlib::Algorithms compression_algorithm() const {
191 return compression_algorithm_();
192 }
193 uint32_t ttl_second() const { return ttl_second_(); }
194 bool is_garbage_collectable() const { return is_garbage_collectable_(); }
195 bool is_volatile() const { return is_volatile_(); }
196 bool enforce_limits() const { return enforce_limits_(); }
197 bool enable_mtime_ns() const { return enable_mtime_ns_(); }
198 unsigned limit_nested_catalog_kentries() const {
199 return limit_nested_catalog_kentries_();
200 }
201 unsigned limit_root_catalog_kentries() const {
202 return limit_root_catalog_kentries_();
203 }
204 unsigned limit_file_size_mb() const { return limit_file_size_mb_(); }
205 bool use_catalog_autobalance() const { return use_catalog_autobalance_(); }
206 unsigned autobalance_max_weight() const { return autobalance_max_weight_(); }
207 unsigned autobalance_min_weight() const { return autobalance_min_weight_(); }
208 bool print_changeset() const { return print_changeset_(); }
209 bool dry_run() const { return dry_run_(); }
210 std::string voms_authz() const { return voms_authz_(); }
211 UnionFsType union_fs() const { return union_fs_(); }
212 std::string lease_path() const { return lease_path_(); }
213 std::string template_from() const { return template_from_(); }
214 std::string template_to() const { return template_to_(); }
215
216 const SettingsSpoolArea &spool_area() const { return spool_area_; }
217 SettingsSpoolArea *GetSpoolArea() { return &spool_area_; }
218
219 bool HasTemplate() const { return !template_to().empty(); }
220
221 private:
222 bool ValidateUnionFs();
223
224 /**
225 * See CVMFS_CREATOR_VERSION
226 */
227 Setting<unsigned> layout_revision_;
228 /**
229 * Set to true if the settings have been created from the environment of
230 * the ephemeral writable shell (cvmfs_server enter command).
231 */
232 Setting<bool> in_enter_session_;
233 /**
234 * The root catalog hash based on which the transaction takes place.
235 * Usually the current root catalog from the manifest, which should be equal
236 * to the root hash of the mounted read-only volume. In some cases, this
237 * can be different though, e.g. for checked out branches or after silent
238 * transactions such as template transactions.
239 */
240 Setting<shash::Any> base_hash_;
241 Setting<shash::Algorithms> hash_algorithm_;
242 Setting<zlib::Algorithms> compression_algorithm_;
243 Setting<uint32_t> ttl_second_;
244 Setting<bool> is_garbage_collectable_;
245 Setting<bool> is_volatile_;
246 Setting<bool> enforce_limits_;
247 Setting<bool> enable_mtime_ns_;
248 Setting<unsigned> limit_nested_catalog_kentries_;
249 Setting<unsigned> limit_root_catalog_kentries_;
250 Setting<unsigned> limit_file_size_mb_;
251 Setting<bool> use_catalog_autobalance_;
252 Setting<unsigned> autobalance_max_weight_;
253 Setting<unsigned> autobalance_min_weight_;
254 Setting<bool> print_changeset_;
255 Setting<bool> dry_run_;
256 Setting<std::string> voms_authz_;
257 Setting<UnionFsType> union_fs_;
258 /**
259 * How long to retry taking a lease before giving up
260 */
261 Setting<unsigned> timeout_s_;
262 Setting<std::string> lease_path_;
263 /**
264 * Used for template transactions where a directory tree gets cloned
265 * (from --> to) as part of opening the transaction
266 */
267 Setting<std::string> template_from_;
268 Setting<std::string> template_to_;
269
270 SettingsSpoolArea spool_area_;
271 }; // class SettingsTransaction
272
273
274 class SettingsGc { }; // class SettingsGc
275
276
277 class SettingsStorage {
278 public:
279 explicit SettingsStorage(const std::string &fqrn)
280 : fqrn_(fqrn)
281 , type_(upload::SpoolerDefinition::Local)
282 , tmp_dir_(std::string("/srv/cvmfs/") + fqrn + "/data/txn")
283 , endpoint_(std::string("/srv/cvmfs/") + fqrn) { }
284
285 std::string GetLocator() const;
286 void SetLocator(const std::string &locator);
287 void MakeLocal(const std::string &path);
288 void MakeS3(const std::string &s3_config, const std::string &tmp_dir);
289 void MakeGateway(const std::string &host, unsigned port,
290 const std::string &tmp_dir);
291
292 upload::SpoolerDefinition::DriverType type() const { return type_(); }
293 std::string endpoint() const { return endpoint_(); }
294
295 private:
296 Setting<std::string> fqrn_;
297 Setting<upload::SpoolerDefinition::DriverType> type_;
298 Setting<std::string> tmp_dir_;
299 Setting<std::string> endpoint_;
300 }; // class SettingsStorage
301
302
303 class SettingsKeychain {
304 public:
305 explicit SettingsKeychain(const std::string &fqrn)
306 : fqrn_(fqrn)
307 , keychain_dir_("/etc/cvmfs/keys")
308 , master_private_key_path_(keychain_dir_() + "/" + fqrn + ".masterkey")
309 , master_public_key_path_(keychain_dir_() + "/" + fqrn + ".pub")
310 , private_key_path_(keychain_dir_() + "/" + fqrn + ".key")
311 , certificate_path_(keychain_dir_() + "/" + fqrn + ".crt")
312 , gw_key_path_(keychain_dir_() + "/" + fqrn + ".gw") { }
313
314 void SetKeychainDir(const std::string &keychain_dir);
315
316 bool HasDanglingMasterKeys() const;
317 bool HasMasterKeys() const;
318 bool HasDanglingRepositoryKeys() const;
319 bool HasRepositoryKeys() const;
320 bool HasGatewayKey() const;
321
322 std::string keychain_dir() const { return keychain_dir_(); }
323 std::string master_private_key_path() const {
324 return master_private_key_path_();
325 }
326 std::string master_public_key_path() const {
327 return master_public_key_path_();
328 }
329 std::string private_key_path() const { return private_key_path_(); }
330 std::string certificate_path() const { return certificate_path_(); }
331 std::string gw_key_path() const { return gw_key_path_(); }
332
333 private:
334 Setting<std::string> fqrn_;
335 Setting<std::string> keychain_dir_;
336 Setting<std::string> master_private_key_path_;
337 Setting<std::string> master_public_key_path_;
338 Setting<std::string> private_key_path_;
339 Setting<std::string> certificate_path_;
340 Setting<std::string> gw_key_path_;
341 }; // class SettingsKeychain
342
343
344 class SettingsPublisher;
345 class SettingsReplica;
346
347 /**
348 * Description of a read-only repository
349 */
350 class SettingsRepository {
351 public:
352 explicit SettingsRepository(const std::string &fqrn)
353 : fqrn_(fqrn)
354 , url_(std::string("http://localhost/cvmfs/") + fqrn_())
355 , proxy_("")
356 , tmp_dir_("/tmp")
357 , keychain_(fqrn) { }
358 explicit SettingsRepository(const SettingsPublisher &settings_publisher);
359 explicit SettingsRepository(const SettingsReplica &settings_replica);
360
361 void SetUrl(const std::string &url);
362 void SetProxy(const std::string &proxy);
363 void SetTmpDir(const std::string &tmp_dir);
364 void SetCertBundle(const std::string &cert_bundle);
365
366 std::string fqrn() const { return fqrn_(); }
367 std::string url() const { return url_(); }
368 std::string proxy() const { return proxy_(); }
369 std::string tmp_dir() const { return tmp_dir_(); }
370 std::string cert_bundle() const { return cert_bundle_(); }
371
372 const SettingsKeychain &keychain() const { return keychain_; }
373 SettingsKeychain *GetKeychain() { return &keychain_; }
374
375 private:
376 Setting<std::string> fqrn_;
377 Setting<std::string> url_;
378 Setting<std::string> proxy_;
379 Setting<std::string> tmp_dir_;
380 // Currently only used for testing, steered by X509_CERT_BUNDLE
381 // in /etc/cvmfs/server.local
382 Setting<std::string> cert_bundle_;
383
384 SettingsKeychain keychain_;
385 }; // class SettingsRepository
386
387
388 /**
389 * Description of an editable repository.
390 */
391 class SettingsPublisher {
392 public:
393 static const unsigned kDefaultWhitelistValidity; // 30 days
394
395 explicit SettingsPublisher(const std::string &fqrn)
396 : fqrn_(fqrn)
397 , url_(std::string("http://localhost/cvmfs/") + fqrn)
398 , proxy_("")
399 , owner_uid_(0)
400 , owner_gid_(0)
401 , whitelist_validity_days_(kDefaultWhitelistValidity)
402 , is_silent_(false)
403 , is_managed_(false)
404 , ignore_invalid_lease_(false)
405 , storage_(fqrn_())
406 , transaction_(fqrn_())
407 , keychain_(fqrn_()) { }
408 explicit SettingsPublisher(const SettingsRepository &settings_repository);
409
410 void SetUrl(const std::string &url);
411 void SetProxy(const std::string &proxy);
412 void SetOwner(const std::string &user_name);
413 void SetOwner(uid_t uid, gid_t gid);
414 void SetIsSilent(bool value);
415 void SetIsManaged(bool value);
416 void SetIgnoreInvalidLease(bool value);
417
418 std::string GetReadOnlyXAttr(const std::string &attr);
419
420 std::string fqrn() const { return fqrn_(); }
421 std::string url() const { return url_(); }
422 std::string proxy() const { return proxy_(); }
423 unsigned whitelist_validity_days() const {
424 return whitelist_validity_days_();
425 }
426 uid_t owner_uid() const { return owner_uid_(); }
427 uid_t owner_gid() const { return owner_gid_(); }
428 bool is_silent() const { return is_silent_(); }
429 bool is_managed() const { return is_managed_(); }
430 bool ignore_invalid_lease() const { return ignore_invalid_lease_(); }
431
432 const SettingsStorage &storage() const { return storage_; }
433 const SettingsTransaction &transaction() const { return transaction_; }
434 const SettingsKeychain &keychain() const { return keychain_; }
435 SettingsStorage *GetStorage() { return &storage_; }
436 SettingsTransaction *GetTransaction() { return &transaction_; }
437 SettingsKeychain *GetKeychain() { return &keychain_; }
438
439 private:
440 Setting<std::string> fqrn_;
441 Setting<std::string> url_;
442 Setting<std::string> proxy_;
443 Setting<uid_t> owner_uid_;
444 Setting<gid_t> owner_gid_;
445 Setting<unsigned> whitelist_validity_days_;
446 Setting<bool> is_silent_;
447 Setting<bool> is_managed_;
448 // When trying to drop the session, ignore an invalid lease failure. Useful
449 // to recover a publisher with abort -f.
450 Setting<bool> ignore_invalid_lease_;
451
452 SettingsStorage storage_;
453 SettingsTransaction transaction_;
454 SettingsKeychain keychain_;
455 }; // SettingsPublisher
456
457
458 /**
459 * Description of a stratum 1
460 */
461 class SettingsReplica {
462 public:
463 explicit SettingsReplica(const std::string &fqrn)
464 : fqrn_(fqrn)
465 , alias_(fqrn)
466 , url_(std::string("http://localhost/cvmfs/") + alias_()) { }
467
468 std::string fqrn() const { return fqrn_(); }
469 std::string url() const { return url_(); }
470
471 private:
472 Setting<std::string> fqrn_;
473 Setting<std::string> alias_;
474 Setting<std::string> url_;
475 }; // class SettingsReplica
476
477
478 /**
479 * Create Settings objects from the system configuration in
480 * /etc/cvmfs/repositories.d
481 */
482 class SettingsBuilder : SingleCopy {
483 public:
484 SettingsBuilder()
485 : config_path_("/etc/cvmfs/repositories.d"), options_mgr_(NULL) { }
486 ~SettingsBuilder();
487 /**
488 * Used in unit tests.
489 */
490 explicit SettingsBuilder(const std::string &c) : config_path_(c) { }
491
492 /**
493 * If ident is a url, creates a generic settings object inferring the fqrn
494 * from the url.
495 * Otherwise, looks in the config files in /etc/cvmfs/repositories.d/<alias>/
496 * If alias is an empty string, the command still succeeds iff there is a
497 * single repository under /etc/cvmfs/repositories.d
498 */
499 SettingsRepository CreateSettingsRepository(const std::string &ident);
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 * If needs_managed is true, remote repositories are rejected
508 * In an "enter environment" (see cmd_enter), the spool area of the enter
509 * environment is applied.
510 */
511
512 SettingsPublisher *CreateSettingsPublisher(const std::string &ident,
513 bool needs_managed = false);
514
515 OptionsManager *options_mgr() const { return options_mgr_; }
516 bool IsManagedRepository() const { return options_mgr_ != NULL; }
517
518 /**
519 * Get the values from the server configuration and set them to the publisher
520 * settings.
521 */
522 void ApplyOptionsFromServerPath(const OptionsManager &options_mgr_,
523 SettingsPublisher *settings_publisher);
524
525 void SetConfigPath(const std::string &config_path) {
526 config_path_ = config_path;
527 }
528
529 private:
530 /**
531 * For non locally managed repositories, a configuration file should be
532 * provided in order to publish from the ephemeral shell through the gateway
533 */
534 std::string config_path_;
535
536 /**
537 * For locally managed repositories, the options manager is non NULL and
538 * contains the configuration after a call to CreateSettingsRepository()
539 */
540 OptionsManager *options_mgr_;
541 // TODO(avalenzu): options_mgr_ should become a unique pointer.
542
543 /**
544 * Returns the name of the one and only repository under kConfigPath
545 * Throws an exception if there are none or multiple repositories.
546 * The alias is usually the fqrn except for a replica with an explicit
547 * alias set different from the fqrn (e.g. if Stratum 0 and 1 are hosted)
548 * on the same node.
549 */
550 std::string GetSingleAlias();
551
552 /**
553 * If in a ephemeral writable shell, parse $session_dir/env.conf
554 * Otherwise return an empty map. A non-empty map has at least CVMFS_FQRN set.
555 */
556 std::map<std::string, std::string> GetSessionEnvironment();
557
558 /**
559 * Create settings from an ephermal writable shell
560 */
561 SettingsPublisher *CreateSettingsPublisherFromSession();
562 }; // class SettingsBuilder
563
564 } // namespace publish
565
566 #endif // CVMFS_PUBLISH_SETTINGS_H_
567