GCC Code Coverage Report


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