Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

daemon: API to reset the session.base instance #1757

Merged
merged 8 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions dnf5daemon-server/dbus/interfaces/org.rpm.dnf.v0.Base.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
<arg name="error_msg" type="s" direction="out"/>
</method>

<!--
reset:
@success: `true` if the session was successfully resetted, `false` otherwise.
@error_msg: string, contains errors encountered while resetting the session

Completely reset the session.
-->
<method name="reset">
<arg name="success" type="b" direction="out"/>
<arg name="error_msg" type="s" direction="out"/>
</method>

<!--
download_add_new:
@session_object_path: object path of the dnf5daemon session
Expand Down
29 changes: 29 additions & 0 deletions dnf5daemon-server/services/base/base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
#include <unistd.h>

#include <iostream>
#include <mutex>
#include <string>
#include <thread>
#include <unordered_set>
Expand Down Expand Up @@ -58,6 +59,16 @@ void Base::dbus_register() {
[this](sdbus::MethodCall call) -> void {
session.get_threads_manager().handle_method(*this, &Base::clean, call, session.session_locale);
});
dbus_object->registerMethod(
dnfdaemon::INTERFACE_BASE,
"reset",
"",
{},
"bs",
{"success", "error_msg"},
[this](sdbus::MethodCall call) -> void {
session.get_threads_manager().handle_method(*this, &Base::reset, call, session.session_locale);
});

dbus_object->registerSignal(
dnfdaemon::INTERFACE_BASE,
Expand Down Expand Up @@ -147,3 +158,21 @@ sdbus::MethodReply Base::clean(sdbus::MethodCall & call) {
reply << error_msg;
return reply;
}

sdbus::MethodReply Base::reset(sdbus::MethodCall & call) {
bool success{true};
std::string error_msg{};

auto & transaction_mutex = session.get_transaction_mutex();
if (!transaction_mutex.try_lock()) {
success = false;
error_msg = "Cannot reset, an rpm transaction is running.";
} else {
std::lock_guard<std::mutex> transaction_lock(transaction_mutex, std::adopt_lock);
session.reset_base();
}
auto reply = call.createReply();
reply << success;
reply << error_msg;
return reply;
}
1 change: 1 addition & 0 deletions dnf5daemon-server/services/base/base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Base : public IDbusSessionService {

private:
sdbus::MethodReply clean(sdbus::MethodCall & call);
sdbus::MethodReply reset(sdbus::MethodCall & call);
sdbus::MethodReply read_all_repos(sdbus::MethodCall & call);
};

Expand Down
15 changes: 15 additions & 0 deletions dnf5daemon-server/services/goal/goal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ void Goal::dbus_register() {
}

sdbus::MethodReply Goal::resolve(sdbus::MethodCall & call) {
auto & transaction_mutex = session.get_transaction_mutex();
if (!transaction_mutex.try_lock()) {
//TODO(mblaha): use specialized exception class
throw std::runtime_error("Cannot acquire transaction lock (another transaction is running).");
}
std::lock_guard<std::mutex> transaction_lock(transaction_mutex, std::adopt_lock);

// read options from dbus call
dnfdaemon::KeyValueMap options;
call >> options;
Expand Down Expand Up @@ -283,6 +290,14 @@ sdbus::MethodReply Goal::do_transaction(sdbus::MethodCall & call) {
if (!session.check_authorization(dnfdaemon::POLKIT_EXECUTE_RPM_TRANSACTION, call.getSender())) {
throw std::runtime_error("Not authorized");
}

auto & transaction_mutex = session.get_transaction_mutex();
jan-kolarik marked this conversation as resolved.
Show resolved Hide resolved
if (!transaction_mutex.try_lock()) {
//TODO(mblaha): use specialized exception class
throw std::runtime_error("Cannot acquire transaction lock (another transaction is running).");
}
std::lock_guard<std::mutex> transaction_lock(transaction_mutex, std::adopt_lock);

session.set_cancel_download(Session::CancelDownload::NOT_REQUESTED);

// read options from dbus call
Expand Down
60 changes: 38 additions & 22 deletions dnf5daemon-server/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
#include "utils.hpp"

#include <libdnf5/conf/const.hpp>
#include <libdnf5/logger/stream_logger.hpp>
#include <libdnf5/repo/package_downloader.hpp>
#include <libdnf5/transaction/offline.hpp>
#include <libdnf5/utils/fs/file.hpp>
Expand Down Expand Up @@ -71,27 +72,16 @@ static const std::unordered_set<std::string> ALLOWED_MAIN_CONF_OVERRIDES = {
"strict",
};

Session::Session(
std::vector<std::unique_ptr<libdnf5::Logger>> && loggers,
sdbus::IConnection & connection,
dnfdaemon::KeyValueMap session_configuration,
std::string object_path,
std::string sender)
: connection(connection),
base(std::make_unique<libdnf5::Base>(std::move(loggers))),
goal(*base),
session_configuration(session_configuration),
object_path(object_path),
sender(sender) {
if (session_configuration.find("locale") != session_configuration.end()) {
session_locale = session_configuration_value<std::string>("locale");
}
void Session::setup_base() {
std::vector<std::unique_ptr<libdnf5::Logger>> loggers;
loggers.emplace_back(std::make_unique<libdnf5::StdCStreamLogger>(std::cerr));
base = std::make_unique<libdnf5::Base>(std::move(loggers));

auto & config = base->get_config();

// adjust base.config from session_configuration config overrides
std::map<std::string, std::string> default_overrides{};
auto conf_overrides = session_configuration_value<std::map<std::string, std::string>>("config", default_overrides);
auto conf_overrides =
session_configuration_value<std::map<std::string, std::string>>("config", std::map<std::string, std::string>{});
auto opt_binds = config.opt_binds();
std::optional<bool> am_i_root;
for (auto & opt : conf_overrides) {
Expand Down Expand Up @@ -122,14 +112,39 @@ Session::Session(
base->load_config();

// set variables
base->setup();
if (session_configuration.find("releasever") != session_configuration.end()) {
auto releasever = session_configuration_value<std::string>("releasever");
base->get_vars()->set("releasever", releasever);
}

base->setup();

// load repo configuration
base->get_repo_sack()->create_repos_from_system_configuration();
repositories_status = dnfdaemon::RepoStatus::NOT_READY;

base->set_download_callbacks(std::make_unique<dnf5daemon::DownloadCB>(*this));

// Goal and Transaction instances depend on the base, so reset them as well
goal = std::make_unique<libdnf5::Goal>(*base);
transaction.reset(nullptr);
}

Session::Session(
sdbus::IConnection & connection,
dnfdaemon::KeyValueMap session_configuration,
std::string object_path,
std::string sender)
: connection(connection),
session_configuration(session_configuration),
object_path(object_path),
sender(sender) {
if (session_configuration.find("locale") != session_configuration.end()) {
session_locale = session_configuration_value<std::string>("locale");
}

dbus_object = sdbus::createObject(connection, object_path);
setup_base();

// instantiate all services provided by the daemon
services.emplace_back(std::make_unique<Base>(*this));
Expand All @@ -140,14 +155,11 @@ Session::Session(
services.emplace_back(std::make_unique<Group>(*this));
services.emplace_back(std::make_unique<dnfdaemon::Advisory>(*this));

dbus_object = sdbus::createObject(connection, object_path);
// Register all provided services on d-bus
for (auto & s : services) {
s->dbus_register();
}
dbus_object->finishRegistration();

base->set_download_callbacks(std::make_unique<dnf5daemon::DownloadCB>(*this));
}

Session::~Session() {
Expand Down Expand Up @@ -380,5 +392,9 @@ void Session::store_transaction_offline() {

void Session::reset_goal() {
transaction.reset(nullptr);
goal.reset();
goal->reset();
}

void Session::reset_base() {
setup_base();
}
11 changes: 8 additions & 3 deletions dnf5daemon-server/session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ class Session {
public:
enum class CancelDownload { NOT_RUNNING, NOT_REQUESTED, REQUESTED, NOT_ALLOWED };
Session(
std::vector<std::unique_ptr<libdnf5::Logger>> && loggers,
sdbus::IConnection & connection,
dnfdaemon::KeyValueMap session_configuration,
std::string object_path,
Expand All @@ -75,7 +74,7 @@ class Session {
libdnf5::Base * get_base() { return base.get(); };
ThreadsManager & get_threads_manager() { return threads_manager; };
sdbus::IObject * get_dbus_object() { return dbus_object.get(); };
libdnf5::Goal & get_goal() { return goal; };
libdnf5::Goal & get_goal() { return *goal; };
libdnf5::base::Transaction * get_transaction() { return transaction.get(); };
void set_transaction(const libdnf5::base::Transaction & src) {
transaction.reset(new libdnf5::base::Transaction(src));
Expand All @@ -99,12 +98,17 @@ class Session {
/// Setter for download cancel request flag.
void set_cancel_download(CancelDownload value) { cancel_download.store(value); }

std::mutex & get_transaction_mutex() { return transaction_mutex; }

void reset_goal();
void reset_base();

private:
void setup_base();

sdbus::IConnection & connection;
std::unique_ptr<libdnf5::Base> base;
libdnf5::Goal goal;
std::unique_ptr<libdnf5::Goal> goal;
std::unique_ptr<libdnf5::base::Transaction> transaction{nullptr};
dnfdaemon::KeyValueMap session_configuration;
sdbus::ObjectPath object_path;
Expand All @@ -116,6 +120,7 @@ class Session {
// repository key import confirmation
enum class KeyConfirmationStatus { PENDING, CONFIRMED, REJECTED };
std::mutex key_import_mutex;
std::mutex transaction_mutex;
std::condition_variable key_import_condition;
std::map<std::string, KeyConfirmationStatus> key_import_status{}; // map key_id: confirmation status
std::atomic<CancelDownload> cancel_download{CancelDownload::NOT_RUNNING};
Expand Down
7 changes: 1 addition & 6 deletions dnf5daemon-server/session_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,9 @@ sdbus::MethodReply SessionManager::open_session(sdbus::MethodCall & call) {
const std::string sessionid = dnfdaemon::DBUS_OBJECT_PATH + std::string("/") + gen_session_id();
// store newly created session
{
// create a vector of loggers with one logger
std::vector<std::unique_ptr<libdnf5::Logger>> loggers;
loggers.emplace_back(std::make_unique<libdnf5::StdCStreamLogger>(std::cerr));

std::lock_guard<std::mutex> lock(sessions_mutex);
sessions[sender].emplace(
sessionid,
std::make_unique<Session>(std::move(loggers), *connection, std::move(configuration), sessionid, sender));
sessionid, std::make_unique<Session>(*connection, std::move(configuration), sessionid, sender));
}

auto reply = call.createReply();
Expand Down
4 changes: 2 additions & 2 deletions test/dnf5daemon-server/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@

IFACE_SESSION_MANAGER = '{}.SessionManager'.format(DNFDAEMON_BUS_NAME)
IFACE_REPO = '{}.rpm.Repo'.format(DNFDAEMON_BUS_NAME)
IFACE_REPOCONF = '{}.rpm.RepoConf'.format(DNFDAEMON_BUS_NAME)
IFACE_RPM = '{}.rpm.Rpm'.format(DNFDAEMON_BUS_NAME)
IFACE_GOAL = '{}.Goal'.format(DNFDAEMON_BUS_NAME)

Expand Down Expand Up @@ -75,7 +74,7 @@ def setUp(self):
"config": {
"config_file_path": self.config_file_path,
"installroot": self.installroot,
"plugins": False,
"plugins": "False",
"cachedir": os.path.join(self.installroot, "var/cache/dnf"),
"reposdir": self.reposdir,
}
Expand All @@ -91,4 +90,5 @@ def setUp(self):
dbus_interface=IFACE_GOAL)

def tearDown(self):
self.iface_session.close_session(self.session)
shutil.rmtree(self.installroot)
4 changes: 3 additions & 1 deletion test/dnf5daemon-server/test_distro_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def test_distro_sync_package(self):
dbus.Dictionary({ # transaction item attrs
}, signature=dbus.Signature('sv')),
dbus.Dictionary({ # package
dbus.String('full_nevra'): dbus.String('one-0:2-1.noarch', variant_level=1),
dbus.String('evr'): dbus.String('2-1', variant_level=1),
dbus.String('name'): dbus.String('one', variant_level=1),
dbus.String('epoch'): dbus.String('0', variant_level=1),
Expand All @@ -72,6 +73,7 @@ def test_distro_sync_package(self):
dbus.Dictionary({ # transaction item attrs
}, signature=dbus.Signature('sv')),
dbus.Dictionary({ # package
dbus.String('full_nevra'): dbus.String('one-0:1-1.noarch', variant_level=1),
dbus.String('evr'): dbus.String('1-1', variant_level=1),
dbus.String('name'): dbus.String('one', variant_level=1),
dbus.String('epoch'): dbus.String('0', variant_level=1),
Expand Down Expand Up @@ -99,7 +101,7 @@ def test_distr_sync_fromrepo(self):
resolved, result = self.iface_goal.resolve(
dbus.Dictionary({}, signature='sv'))

self.assertEqual(result, 1)
self.assertEqual(result, 2)
self.assertEqual(
resolved,
dbus.Array([
Expand Down
4 changes: 3 additions & 1 deletion test/dnf5daemon-server/test_downgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def test_downgrade_package(self):
dbus.Dictionary({ # transaction item attrs
}, signature=dbus.Signature('sv')),
dbus.Dictionary({ # package
dbus.String('full_nevra'): dbus.String('one-0:1-1.noarch', variant_level=1),
dbus.String('evr'): dbus.String('1-1', variant_level=1),
dbus.String('name'): dbus.String('one', variant_level=1),
dbus.String('epoch'): dbus.String('0', variant_level=1),
Expand All @@ -72,6 +73,7 @@ def test_downgrade_package(self):
dbus.Dictionary({ # transaction item attrs
}, signature=dbus.Signature('sv')),
dbus.Dictionary({ # package
dbus.String('full_nevra'): dbus.String('one-0:2-1.noarch', variant_level=1),
dbus.String('evr'): dbus.String('2-1', variant_level=1),
dbus.String('name'): dbus.String('one', variant_level=1),
dbus.String('epoch'): dbus.String('0', variant_level=1),
Expand Down Expand Up @@ -99,7 +101,7 @@ def test_downgrade_fromrepo(self):
resolved, result = self.iface_goal.resolve(
dbus.Dictionary({}, signature='sv'))

self.assertEqual(result, 1)
self.assertEqual(result, 2)
self.assertCountEqual(
resolved,
dbus.Array([
Expand Down
2 changes: 2 additions & 0 deletions test/dnf5daemon-server/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def test_install_package(self):
dbus.Dictionary({ # transaction item attrs
}, signature=dbus.Signature('sv')),
dbus.Dictionary({ # package
dbus.String('full_nevra'): dbus.String('one-0:2-1.noarch', variant_level=1),
dbus.String('arch'): dbus.String('noarch', variant_level=1),
dbus.String('epoch'): dbus.String('0', variant_level=1),
dbus.String('evr'): dbus.String('2-1', variant_level=1),
Expand Down Expand Up @@ -141,6 +142,7 @@ def test_install_file(self):
dbus.Dictionary({ # transaction item attrs
}, signature=dbus.Signature('sv')),
dbus.Dictionary({ # package
dbus.String('full_nevra'): dbus.String('one-0:1-1.noarch', variant_level=1),
dbus.String('arch'): dbus.String('noarch', variant_level=1),
dbus.String('epoch'): dbus.String('0', variant_level=1),
dbus.String('evr'): dbus.String('1-1', variant_level=1),
Expand Down
2 changes: 2 additions & 0 deletions test/dnf5daemon-server/test_reinstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def test_reinstall_package(self):
dbus.Dictionary({ # transaction item attrs
}, signature=dbus.Signature('sv')),
dbus.Dictionary({ # package
dbus.String('full_nevra'): dbus.String('one-0:1-1.noarch', variant_level=1),
dbus.String('evr'): dbus.String('1-1', variant_level=1),
dbus.String('name'): dbus.String('one', variant_level=1),
dbus.String('epoch'): dbus.String('0', variant_level=1),
Expand All @@ -72,6 +73,7 @@ def test_reinstall_package(self):
dbus.Dictionary({ # transaction item attrs
}, signature=dbus.Signature('sv')),
dbus.Dictionary({ # package
dbus.String('full_nevra'): dbus.String('one-0:1-1.noarch', variant_level=1),
dbus.String('evr'): dbus.String('1-1', variant_level=1),
dbus.String('name'): dbus.String('one', variant_level=1),
dbus.String('epoch'): dbus.String('0', variant_level=1),
Expand Down
1 change: 1 addition & 0 deletions test/dnf5daemon-server/test_remove.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def test_remove_package(self):
dbus.Dictionary({ # transaction item attrs
}, signature=dbus.Signature('sv')),
dbus.Dictionary({ # package
dbus.String('full_nevra'): dbus.String('one-0:1-1.noarch', variant_level=1),
dbus.String('arch'): dbus.String('noarch', variant_level=1),
dbus.String('epoch'): dbus.String('0', variant_level=1),
dbus.String('evr'): dbus.String('1-1', variant_level=1),
Expand Down
Loading
Loading