2021-01-25 00:24:31 +01:00
|
|
|
#ifndef LIBREPOMGR_SERVER_SETUP_H
|
|
|
|
#define LIBREPOMGR_SERVER_SETUP_H
|
|
|
|
|
|
|
|
#include "./authentication.h"
|
|
|
|
#include "./buildactions/buildaction.h"
|
|
|
|
#include "./buildactions/buildactiontemplate.h"
|
2021-02-26 01:39:21 +01:00
|
|
|
#include "./globallock.h"
|
2022-04-23 19:39:31 +02:00
|
|
|
#include "./resourceusage.h"
|
2021-01-25 00:24:31 +01:00
|
|
|
|
|
|
|
#include "../libpkg/data/config.h"
|
|
|
|
#include "../libpkg/data/lockable.h"
|
|
|
|
|
|
|
|
#include <reflective_rapidjson/json/serializable.h>
|
|
|
|
|
|
|
|
#include <boost/asio/executor_work_guard.hpp>
|
|
|
|
#include <boost/asio/ip/address.hpp>
|
|
|
|
#include <boost/asio/ssl/context.hpp>
|
|
|
|
|
2022-12-22 23:23:42 +01:00
|
|
|
#include <functional>
|
2021-01-25 00:24:31 +01:00
|
|
|
#include <memory>
|
|
|
|
#include <thread>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
namespace LibRepoMgr {
|
|
|
|
|
|
|
|
struct LIBREPOMGR_EXPORT ThreadPool {
|
|
|
|
explicit ThreadPool(const char *name, boost::asio::io_context &ioContext, unsigned short threadCount);
|
|
|
|
~ThreadPool();
|
|
|
|
|
|
|
|
const char *const name;
|
|
|
|
std::vector<std::thread> threads;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ServiceStatus;
|
2022-02-05 22:09:52 +01:00
|
|
|
struct Storage;
|
2021-01-25 00:24:31 +01:00
|
|
|
|
|
|
|
struct LIBREPOMGR_EXPORT ServiceSetup : public LibPkg::Lockable {
|
|
|
|
// the overall configuration (databases, packages, ...) used at various places
|
|
|
|
// -> acquire the config lock for these
|
|
|
|
LibPkg::Config config;
|
|
|
|
|
|
|
|
// service global configuration; only changed when (re)loading config
|
|
|
|
// -> acquire the setup lock for these
|
|
|
|
std::string configFilePath = "server.conf";
|
|
|
|
std::string pacmanConfigFilePath = "/etc/pacman.conf";
|
2021-07-31 14:55:49 +02:00
|
|
|
std::filesystem::path initialWorkingDirectory;
|
2021-01-25 00:24:31 +01:00
|
|
|
std::string workingDirectory = "workingdir";
|
2023-11-08 14:02:47 +01:00
|
|
|
std::string defaultArch = "x86_64";
|
2022-05-15 03:24:10 +02:00
|
|
|
std::string dbPath = "libpkg-1.db";
|
2021-12-05 23:40:51 +01:00
|
|
|
std::uint32_t maxDbs = 512;
|
2022-01-26 00:41:53 +01:00
|
|
|
std::size_t packageCacheLimit = 1000;
|
2021-01-25 00:24:31 +01:00
|
|
|
|
2022-02-05 22:09:52 +01:00
|
|
|
void loadConfigFiles(bool doFirstTimeSetup);
|
2022-03-05 12:34:26 +01:00
|
|
|
void printLimits();
|
2022-02-05 22:09:52 +01:00
|
|
|
void printDatabases();
|
2022-03-20 17:36:12 +01:00
|
|
|
void printIoUringUsage();
|
2022-02-20 20:17:42 +01:00
|
|
|
std::string_view cacheFilePath() const;
|
2022-02-05 22:09:52 +01:00
|
|
|
void restoreState();
|
2022-02-20 20:17:42 +01:00
|
|
|
std::size_t saveState();
|
2022-02-05 22:09:52 +01:00
|
|
|
void initStorage();
|
2022-03-01 00:39:50 +01:00
|
|
|
int run();
|
2022-03-07 23:36:48 +01:00
|
|
|
int fixDb();
|
2022-04-23 19:39:31 +02:00
|
|
|
ServiceStatus computeStatus();
|
2022-02-05 22:09:52 +01:00
|
|
|
|
2021-01-25 00:24:31 +01:00
|
|
|
// variables relevant for the web server; only changed when (re)loading config
|
|
|
|
struct LIBREPOMGR_EXPORT WebServerSetup {
|
|
|
|
// only read by build actions and routes; changed when (re)loading config
|
|
|
|
// -> acquire the setup lock for these
|
|
|
|
std::string staticFilesPath;
|
|
|
|
|
|
|
|
// never changed after setup
|
|
|
|
boost::asio::ip::address address = boost::asio::ip::make_address("127.0.0.1");
|
|
|
|
unsigned short port = 8090;
|
|
|
|
unsigned short threadCount = 1;
|
|
|
|
boost::asio::io_context ioContext;
|
|
|
|
boost::asio::ssl::context sslContext{ boost::asio::ssl::context::sslv23_client };
|
2022-02-25 00:29:43 +01:00
|
|
|
std::atomic_size_t packageSearchResponseLimit = 20000; // sufficient to return a "full architecture"
|
|
|
|
std::atomic_size_t buildActionsResponseLimit = 200;
|
2021-01-25 00:24:31 +01:00
|
|
|
bool verifySslCertificates = true;
|
|
|
|
bool logSslCertificateValidation = false;
|
|
|
|
|
|
|
|
void applyConfig(const std::multimap<std::string, std::string> &multimap);
|
|
|
|
void initSsl();
|
|
|
|
static bool logCertificateValidation(bool preVerified, boost::asio::ssl::verify_context &context);
|
|
|
|
} webServer;
|
|
|
|
|
|
|
|
// variables relevant for build actions and web server routes dealing with them
|
|
|
|
struct LIBREPOMGR_EXPORT BuildSetup : public LibPkg::Lockable {
|
2022-02-05 22:09:52 +01:00
|
|
|
friend void ServiceSetup::restoreState();
|
|
|
|
|
2021-01-25 00:24:31 +01:00
|
|
|
struct LIBREPOMGR_EXPORT Worker : private boost::asio::executor_work_guard<boost::asio::io_context::executor_type>, public ThreadPool {
|
|
|
|
explicit Worker(BuildSetup &setup);
|
|
|
|
~Worker();
|
|
|
|
BuildSetup &setup;
|
|
|
|
};
|
|
|
|
|
2022-11-24 21:33:42 +01:00
|
|
|
enum class VisitorBehavior {
|
|
|
|
DiscardChanges,
|
|
|
|
SaveChanges,
|
|
|
|
Delete,
|
|
|
|
};
|
|
|
|
|
2022-02-05 22:09:52 +01:00
|
|
|
explicit BuildSetup();
|
|
|
|
BuildSetup(BuildSetup &&) = delete;
|
|
|
|
~BuildSetup();
|
2021-01-25 00:24:31 +01:00
|
|
|
|
|
|
|
// fields which have their own locking
|
|
|
|
// -> acquire the object's lock
|
|
|
|
BuildActionMetaInfo metaInfo; // only static data so far but maybe extended to allow defining custom build actions
|
|
|
|
|
|
|
|
// only read by build actions and routes; changed when (re)loading config
|
|
|
|
// -> acquire the setup lock for these
|
|
|
|
std::string workingDirectory = "building";
|
|
|
|
std::vector<std::string> pkgbuildsDirs;
|
|
|
|
std::regex ignoreLocalPkgbuildsRegex;
|
|
|
|
std::string makePkgPath = "makepkg";
|
|
|
|
std::string makeChrootPkgPath = "makechrootpkg";
|
2022-06-12 20:42:14 +02:00
|
|
|
std::string makeContainerPkgPath = "makecontainerpkg";
|
2021-01-25 00:24:31 +01:00
|
|
|
std::string updatePkgSumsPath = "updpkgsums";
|
|
|
|
std::string repoAddPath = "repo-add";
|
|
|
|
std::string repoRemovePath = "repo-remove";
|
2023-04-07 17:52:52 +02:00
|
|
|
std::string pacmanPath = "pacman";
|
|
|
|
std::string paccachePath = "paccache";
|
2023-05-28 22:05:02 +02:00
|
|
|
std::string pkgctlPath = "pkgctl";
|
2021-03-14 21:53:51 +01:00
|
|
|
std::string gpgPath = "gpg";
|
2021-01-25 00:24:31 +01:00
|
|
|
std::string ccacheDir;
|
|
|
|
std::string chrootDir;
|
|
|
|
std::string chrootRootUser = "root";
|
|
|
|
std::string chrootDefaultUser = "buildservice";
|
2021-03-14 21:53:51 +01:00
|
|
|
std::string defaultGpgKey;
|
2021-01-25 00:24:31 +01:00
|
|
|
std::string pacmanConfigFilePath; // FIXME: not useful after all?; using config-$arch directory within chrootDir instead
|
|
|
|
std::string makepkgConfigFilePath; // FIXME: not useful after all?; using config-$arch directory within chrootDir instead
|
|
|
|
std::vector<std::string> makechrootpkgFlags;
|
|
|
|
std::vector<std::string> makepkgFlags;
|
2022-05-31 20:27:42 +02:00
|
|
|
std::string packageCacheDir; // cache dir *without* architecture sub-folder (which is automatically added as needed)
|
2021-07-12 14:45:44 +02:00
|
|
|
std::uint64_t packageDownloadSizeLimit = 500 * 1024 * 1024;
|
2021-01-25 00:24:31 +01:00
|
|
|
std::string testFilesDir;
|
|
|
|
BuildPresets presets;
|
|
|
|
bool loadFilesDbs = false;
|
2022-01-25 00:13:10 +01:00
|
|
|
bool forceLoadingDbs = false;
|
2021-01-25 00:24:31 +01:00
|
|
|
|
|
|
|
// never changed after startup
|
|
|
|
unsigned short threadCount = 4;
|
|
|
|
boost::asio::io_context ioContext;
|
2022-05-15 03:24:10 +02:00
|
|
|
std::string dbPath = "librepomgr-1.db";
|
2021-01-25 00:24:31 +01:00
|
|
|
|
2022-02-05 22:09:52 +01:00
|
|
|
void initStorage(const char *path);
|
|
|
|
bool hasStorage() const;
|
2021-01-25 00:24:31 +01:00
|
|
|
void applyConfig(const std::multimap<std::string, std::string> &multimap);
|
|
|
|
void readPresets(const std::string &configFilePath, const std::string &presetsFile);
|
|
|
|
Worker allocateBuildWorker();
|
2022-02-05 22:09:52 +01:00
|
|
|
LibPkg::StorageID allocateBuildActionID();
|
|
|
|
std::shared_ptr<BuildAction> getBuildAction(BuildActionIdType id);
|
|
|
|
std::vector<std::shared_ptr<BuildAction>> getBuildActions(const std::vector<BuildActionIdType> &ids);
|
|
|
|
LibPkg::StorageID storeBuildAction(const std::shared_ptr<BuildAction> &buildAction);
|
|
|
|
void deleteBuildAction(const std::vector<std::shared_ptr<BuildAction>> &actions);
|
|
|
|
std::size_t buildActionCount();
|
2022-04-23 19:39:31 +02:00
|
|
|
std::size_t runningBuildActionCount() const;
|
2022-03-07 23:36:48 +01:00
|
|
|
void rebuildDb();
|
2022-05-31 20:54:02 +02:00
|
|
|
using BuildActionVisitorBase = std::function<bool(LibPkg::StorageID, BuildActionBase &&)>;
|
|
|
|
void forEachBuildAction(std::function<void(std::size_t)> count, BuildActionVisitorBase &&func, std::size_t limit, std::size_t start);
|
2022-11-24 21:33:42 +01:00
|
|
|
using BuildActionVisitorWriteable = std::function<bool(LibPkg::StorageID, BuildAction &, VisitorBehavior &)>;
|
|
|
|
void forEachBuildAction(BuildActionVisitorWriteable &&func, std::size_t *count = nullptr);
|
2022-02-05 22:09:52 +01:00
|
|
|
std::vector<std::shared_ptr<BuildAction>> followUpBuildActions(BuildActionIdType forId);
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::unordered_map<BuildActionIdType, std::shared_ptr<BuildAction>> m_runningActions;
|
|
|
|
std::unordered_map<BuildActionIdType, std::unordered_set<BuildActionIdType>> m_followUpActions;
|
|
|
|
std::unique_ptr<Storage> m_storage;
|
2021-01-25 00:24:31 +01:00
|
|
|
} building;
|
|
|
|
|
|
|
|
struct LIBREPOMGR_EXPORT Authentication : public LibPkg::Lockable {
|
|
|
|
std::unordered_map<std::string, UserInfo> users;
|
|
|
|
|
|
|
|
void applyConfig(const std::string &userName, const std::multimap<std::string, std::string> &multimap);
|
2022-07-10 17:18:29 +02:00
|
|
|
UserAuth authenticate(std::string_view authorizationHeader) const;
|
2021-01-25 00:24:31 +01:00
|
|
|
} auth;
|
|
|
|
|
2021-02-20 23:25:31 +01:00
|
|
|
struct LIBREPOMGR_EXPORT Locks {
|
2021-03-02 18:30:15 +01:00
|
|
|
using LockTable = std::unordered_map<std::string, GlobalLockable>;
|
|
|
|
|
2021-07-25 00:39:49 +02:00
|
|
|
[[nodiscard]] GlobalLockable &namedLock(const std::string &lockName);
|
2021-02-26 01:39:21 +01:00
|
|
|
[[nodiscard]] SharedLoggingLock acquireToRead(LogContext &log, std::string &&lockName);
|
|
|
|
[[nodiscard]] UniqueLoggingLock acquireToWrite(LogContext &log, std::string &&lockName);
|
2021-07-25 00:39:49 +02:00
|
|
|
[[nodiscard]] std::pair<LockTable *, std::unique_lock<std::shared_mutex>> acquireLockTable();
|
2022-12-22 23:23:42 +01:00
|
|
|
void acquireToRead(LogContext &log, std::string &&name, std::move_only_function<void(SharedLoggingLock &&lock)> &&callback);
|
|
|
|
void acquireToWrite(LogContext &log, std::string &&name, std::move_only_function<void(UniqueLoggingLock &&lock)> &&callback);
|
2021-02-20 23:25:31 +01:00
|
|
|
void clear();
|
2021-02-22 23:44:06 +01:00
|
|
|
static std::string forDatabase(std::string_view dbName, std::string_view dbArch);
|
|
|
|
static std::string forDatabase(const LibPkg::Database &db);
|
2021-02-20 23:25:31 +01:00
|
|
|
|
|
|
|
private:
|
2021-07-25 00:39:49 +02:00
|
|
|
std::mutex m_accessMutex;
|
|
|
|
std::shared_mutex m_cleanupMutex;
|
2021-03-02 18:30:15 +01:00
|
|
|
LockTable m_locksByName;
|
2021-02-20 23:25:31 +01:00
|
|
|
} locks;
|
2021-01-25 00:24:31 +01:00
|
|
|
};
|
|
|
|
|
2022-02-05 22:09:52 +01:00
|
|
|
inline bool ServiceSetup::BuildSetup::hasStorage() const
|
|
|
|
{
|
|
|
|
return m_storage != nullptr;
|
|
|
|
}
|
|
|
|
|
2022-04-23 19:39:31 +02:00
|
|
|
inline std::size_t ServiceSetup::BuildSetup::runningBuildActionCount() const
|
2021-01-25 00:24:31 +01:00
|
|
|
{
|
2022-02-05 22:09:52 +01:00
|
|
|
return m_runningActions.size();
|
2021-01-25 00:24:31 +01:00
|
|
|
}
|
|
|
|
|
2021-07-25 00:39:49 +02:00
|
|
|
inline GlobalLockable &ServiceSetup::Locks::namedLock(const std::string &lockName)
|
|
|
|
{
|
|
|
|
const auto locktableLock = std::unique_lock(m_accessMutex);
|
|
|
|
return m_locksByName[lockName];
|
|
|
|
}
|
|
|
|
|
2021-02-26 01:39:21 +01:00
|
|
|
inline SharedLoggingLock ServiceSetup::Locks::acquireToRead(LogContext &log, std::string &&lockName)
|
2021-02-20 23:25:31 +01:00
|
|
|
{
|
2021-07-25 00:39:49 +02:00
|
|
|
const auto locktableLock = std::shared_lock(m_cleanupMutex);
|
|
|
|
return namedLock(lockName).lockToRead(log, std::move(lockName));
|
2021-02-20 23:25:31 +01:00
|
|
|
}
|
|
|
|
|
2021-02-26 01:39:21 +01:00
|
|
|
inline UniqueLoggingLock ServiceSetup::Locks::acquireToWrite(LogContext &log, std::string &&lockName)
|
2021-02-20 23:25:31 +01:00
|
|
|
{
|
2021-07-25 00:39:49 +02:00
|
|
|
const auto locktableLock = std::shared_lock(m_cleanupMutex);
|
|
|
|
return namedLock(lockName).lockToWrite(log, std::move(lockName));
|
2021-02-20 23:25:31 +01:00
|
|
|
}
|
|
|
|
|
2022-12-22 23:23:42 +01:00
|
|
|
inline void ServiceSetup::Locks::acquireToRead(
|
|
|
|
LogContext &log, std::string &&lockName, std::move_only_function<void(SharedLoggingLock &&lock)> &&callback)
|
|
|
|
{
|
|
|
|
const auto locktableLock = std::shared_lock(m_cleanupMutex);
|
|
|
|
namedLock(lockName).lockToRead(log, std::move(lockName), std::move(callback));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void ServiceSetup::Locks::acquireToWrite(
|
|
|
|
LogContext &log, std::string &&lockName, std::move_only_function<void(UniqueLoggingLock &&lock)> &&callback)
|
|
|
|
{
|
|
|
|
const auto locktableLock = std::shared_lock(m_cleanupMutex);
|
|
|
|
namedLock(lockName).lockToWrite(log, std::move(lockName), std::move(callback));
|
|
|
|
}
|
|
|
|
|
2021-07-25 00:39:49 +02:00
|
|
|
inline std::pair<ServiceSetup::Locks::LockTable *, std::unique_lock<std::shared_mutex>> ServiceSetup::Locks::acquireLockTable()
|
2021-03-02 18:30:15 +01:00
|
|
|
{
|
2021-07-25 00:39:49 +02:00
|
|
|
return std::make_pair(&m_locksByName, std::unique_lock(m_cleanupMutex));
|
2021-03-02 18:30:15 +01:00
|
|
|
}
|
|
|
|
|
2021-01-25 00:24:31 +01:00
|
|
|
struct LIBREPOMGR_EXPORT ServiceStatus : public ReflectiveRapidJSON::JsonSerializable<ServiceStatus> {
|
2022-06-09 19:50:43 +02:00
|
|
|
explicit ServiceStatus(ServiceSetup &setup);
|
2021-01-25 00:24:31 +01:00
|
|
|
|
|
|
|
const char *const version = nullptr;
|
2022-06-09 19:50:43 +02:00
|
|
|
const char *const url = nullptr;
|
2021-01-25 00:24:31 +01:00
|
|
|
const LibPkg::Status config;
|
|
|
|
const BuildActionMetaInfo &actions;
|
|
|
|
const BuildPresets &presets;
|
2023-11-08 14:02:47 +01:00
|
|
|
const std::string &defaultArch;
|
2022-04-24 18:25:22 +02:00
|
|
|
const ResourceUsage resourceUsage;
|
2021-01-25 00:24:31 +01:00
|
|
|
};
|
|
|
|
|
2022-04-23 19:39:31 +02:00
|
|
|
inline ServiceStatus ServiceSetup::computeStatus()
|
2021-01-25 00:24:31 +01:00
|
|
|
{
|
|
|
|
return ServiceStatus(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace LibRepoMgr
|
|
|
|
|
|
|
|
#endif // LIBREPOMGR_SERVER_SETUP_H
|