Projects
Eulaceura:Factory
libdnf
_service:obs_scm:backport-Fix-countme-bucket-ca...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:backport-Fix-countme-bucket-calculation.patch of Package libdnf
From a7ef27917f01b32e44d0a5bbf7b06104f8275ec5 Mon Sep 17 00:00:00 2001 From: Michal Domonkos <mdomonko@redhat.com> Date: Wed, 8 May 2024 12:05:21 +0200 Subject: [PATCH] Fix countme bucket calculation Actually use the system's installation time (if known) as the reference point, instead of the first-ever countme event recorded for the given repo. This is what the dnf.conf(5) man page always said about the countme option, the code just never lived up to that. This makes bucket calculation more accurate: 1. System upgrades will no longer reset the bucket to 1 (this used to be the case due to a new persistdir being created whenever $releasever changed). 2. Systems that only reach out to the repos after an initial time period after being installed will no longer appear younger than they really are. 3. Prebuilt OS images that happen to include countme cookies created at build time will no longer cause all the instances spawned from those images (physical machines, VMs or containers) to appear older than they really are. Use the machine-id(5) file's mtime to infer the installation time. This file is semantically tied to the system's lifetime since it's typically populated at installation time or during the first boot by an installer tool or init system, respectively, and remains unchanged. The fact that it's a well-defined file with clear semantics ensures that OS images won't accidentally include a prepopulated version of this file with a timestamp corresponding to the image build, unlike our own cookie files (see point 3 above). In some cases, such as in OCI containers without an init system running, the machine-id file may be missing or empty, even though the system is still used long-term. To cover those, keep the original, relative epoch as a fallback method. System upgrades aren't really a thing for such systems so the above point 1 doesn't apply here. Some containers, such as those created by toolbox(1), may also choose to bind-mount the host's machine-id file, thus falling into the same bucket as their host. Conveniently, that's what we want, since the purpose of such containers is to blend with the host as much as possible. Fixes: #1611 Conflict:NA Reference:https://github.com/rpm-software-management/libdnf/commit/a7ef27917f01b32e44d0a5bbf7b06104f8275ec5 --- libdnf/repo/Repo-private.hpp | 1 + libdnf/repo/Repo.cpp | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/libdnf/repo/Repo-private.hpp b/libdnf/repo/Repo-private.hpp index 1f659e6fb..88cadf7d6 100644 --- a/libdnf/repo/Repo-private.hpp +++ b/libdnf/repo/Repo-private.hpp @@ -91,6 +91,7 @@ class Repo::Impl { void fetch(const std::string & destdir, std::unique_ptr<LrHandle> && h); std::string getCachedir() const; std::string getPersistdir() const; + time_t getSystemEpoch() const; int getAge() const; void expire(); bool isExpired() const; diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp index 40b0b68ec..ead986189 100644 --- a/libdnf/repo/Repo.cpp +++ b/libdnf/repo/Repo.cpp @@ -900,7 +900,7 @@ void Repo::Impl::addCountmeFlag(LrHandle *handle) { // Load the cookie std::string fname = getPersistdir() + "/" + COUNTME_COOKIE; int ver = COUNTME_VERSION; // file format version (for future use) - time_t epoch = 0; // position of first-ever counted window + time_t epoch = 0; // position of first observed window time_t win = COUNTME_OFFSET; // position of last counted window int budget = -1; // budget for this window (-1 = generate) std::ifstream(fname) >> ver >> epoch >> win >> budget; @@ -926,8 +926,15 @@ void Repo::Impl::addCountmeFlag(LrHandle *handle) { // Compute the position of this window win = now - (delta % COUNTME_WINDOW); + + // Compute the epoch from this system's epoch or, if unknown, declare + // this window as the epoch (unless stored in the cookie previously). + time_t sysepoch = getSystemEpoch(); + if (sysepoch) + epoch = sysepoch - ((sysepoch - COUNTME_OFFSET) % COUNTME_WINDOW); if (!epoch) epoch = win; + // Window step (0 at epoch) int step = (win - epoch) / COUNTME_WINDOW; @@ -1221,6 +1228,31 @@ std::string Repo::Impl::getPersistdir() const return result; } +/* Returns this system's installation time ("epoch") as a UNIX timestamp. + * + * Uses the machine-id(5) file's mtime as a good-enough source of truth. This + * file is typically tied to the system's installation or first boot where it's + * populated by an installer tool or init system, respectively, and is never + * changed afterwards. + * + * Some systems, such as containers that don't run an init system, may have the + * file missing, empty or uninitialized, in which case this function returns 0. + */ +time_t Repo::Impl::getSystemEpoch() const +{ + std::string filename = "/etc/machine-id"; + std::string id; + struct stat st; + + if (stat(filename.c_str(), &st) != 0 || !st.st_size) + return 0; + std::ifstream(filename) >> id; + if (id == "uninitialized") + return 0; + + return st.st_mtime; +} + int Repo::Impl::getAge() const { return time(NULL) - mtime(getMetadataPath(MD_TYPE_PRIMARY).c_str());
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2