Daemon model 守护程序模型
Basic architecture recap
基本架构回顾
There are two main contexts in which rpm-ostree is used: on compose servers to generate OSTree commits from RPMs, and on client systems, which consume these OSTree commits to provide transactional upgrades.
rpm-ostree 主要用于两个主要情境:在组合服务器上从 RPM 生成 OSTree 提交,以及在客户端系统上消耗这些 OSTree 提交以提供事务性升级。
The core architecture document describes in details the process by which RPMs are converted into OSTrees on both the compose server and client systems in “hybrid mode”.
核心架构文档详细描述了在“混合模式”下将 RPM 转换为 OSTree 的过程,包括组合服务器和客户端系统。
The rpm-ostree daemon rpm-ostree 守护程序
As described in the administration page, rpm-ostree is the CLI program used on rpm-ostree-based systems to e.g. upgrade, rebase, install packages, etc…
如管理页面中所述,rpm-ostree 是在基于 rpm-ostree 的系统上使用的 CLI 程序,用于升级、重新基于、安装软件包等操作...
These operations follow a client/daemon model where the client talks to the daemon over D-Bus. The reason for this architecture is primarily:
这些操作遵循客户端/守护程序模型,其中客户端通过 D-Bus 与守护程序通信。这种架构的主要原因是:
- to ensure serialization/locking of system mutations
确保系统变化的序列化/锁定 - to make it easier for other clients to manage rpm-ostree-based systems (like Cockpit)
使其他客户端更容易管理基于 rpm-ostree 的系统(如 Cockpit) - to allow unprivileged users to make system mutations via polkit
允许非特权用户通过 polkit 进行系统变更
The D-Bus API is defined in src/daemon/org.projectatomic.rpmostree1.xml
.
D-Bus API 在 src/daemon/org.projectatomic.rpmostree1.xml
中定义。
The rpm-ostree daemon runs as a systemd service which owns the org.projectatomic.rpmostree1
name on the system D-Bus (see src/daemon/rpm-ostreed.service.in
).
rpm-ostree 守护进程作为一个 systemd 服务运行,拥有系统 D-Bus 上的 org.projectatomic.rpmostree1
名称(参见 src/daemon/rpm-ostreed.service.in
)。
When a client wants to talk to the daemon, the D-Bus daemon starts up the systemd service if it’s not already running (see src/daemon/org.projectatomic.rpmostree1.service.in
).
当客户端想要与守护进程通信时,如果 systemd 服务尚未运行,D-Bus 守护进程会启动该服务(参见 src/daemon/org.projectatomic.rpmostree1.service.in
)。
Interacting with the daemon
与守护程序交互
When a user types rpm-ostree upgrade
, at a high-level what happens is that it reaches out to the daemon (starting it if it’s not yet started) and calls the Upgrade()
D-Bus method. You can see its method signature in the XML definition file linked above.
当用户键入 rpm-ostree upgrade
时,高层次上发生的是它与守护程序联系(如果尚未启动,则启动它)并调用 Upgrade()
D-Bus 方法。您可以在上面链接的 XML 定义文件中看到其方法签名。
On the client side, this happens in rpmostree-builtin-upgrade.cxx
where it calls rpmostree_os_call_upgrade_sync
function. This is an auto-generated function (via gdbus-codegen
) which in turns uses glib’s D-Bus bindings to do the actual D-Bus call.
在客户端端,这发生在 rpmostree-builtin-upgrade.cxx
中,它调用 rpmostree_os_call_upgrade_sync
函数。这是一个自动生成的函数(通过 gdbus-codegen
),它反过来使用 glib 的 D-Bus 绑定来执行实际的 D-Bus 调用。
On the daemon side, this call is handled in os_handle_upgrade
(in rpmostreed-os.cxx
) which creates a new DeployTransaction
object (via rpmostreed_transaction_new_deploy
). Transactions are how we ensure that only a single mutation happens at a time, and allow tracking the state of the daemon’s processing of the request.
在守护程序端,此调用在 os_handle_upgrade
(在 rpmostreed-os.cxx
中)中处理,该调用创建一个新的 DeployTransaction
对象(通过 rpmostreed_transaction_new_deploy
)。事务是我们如何确保一次只发生单个变化,并允许跟踪守护程序处理请求的状态。
Transaction objects implement their own separate D-Bus API over an abstract socket. The daemon returns to the client the address of the transaction’s socket and the client then connects to it as a D-Bus peer connection. (Notice how all the methods in the XML return a transaction_address
).
事务对象通过一个抽象套接字实现了自己独立的 D-Bus API。守护程序将事务套接字的地址返回给客户端,然后客户端作为 D-Bus 对等连接到它。(注意 XML 中所有方法返回一个 transaction_address
)。
Once the client is connected to the transaction, it calls its Start()
D-Bus method, which invokes the _execute()
function. In the case of DeployTransaction
, this is deploy_transaction_execute()
in rpmostreed-transaction-types.cxx
.
一旦客户端连接到事务,它调用其 Start()
D-Bus 方法,该方法调用 _execute()
函数。在 DeployTransaction
的情况下,这是 rpmostreed-transaction-types.cxx
中的 deploy_transaction_execute()
。
The client then receives signals from the transaction to monitor the progress of the operation (for example, everytime a message must be printed, a Message
signal is emitted).
客户端然后接收来自事务的信号,以监视操作的进度(例如,每次必须打印消息时,就会发出 Message
信号)。
The same analogous process occurs for other operations. For example, rpm-ostree kargs
creates a KernelArgTransaction
object, which has its execution code in kernel_arg_transaction_execute
.
其他操作也会发生类似的过程。例如, rpm-ostree kargs
创建一个 KernelArgTransaction
对象,该对象在 kernel_arg_transaction_execute
中具有其执行代码。
Once a transaction has finished, it emits the Finished
signal, which tells the client to stop waiting for more updates and disconnect.
一旦事务完成,它会发出 Finished
信号,告诉客户端停止等待更多更新并断开连接。
Polkit 政策工具包
The daemon integrates with polkit, which is a framework for authorizing actions. For example, a local administrator running as its unprivileged uid should be able to call rpm-ostree upgrade
.
该守护程序与政策工具包集成,政策工具包是用于授权操作的框架。例如,作为其非特权 uid 运行的本地管理员应该能够调用 rpm-ostree upgrade
。
How this works is that the daemon converts D-Bus method calls like Upgrade()
into polkit actions in os_authorize_method
. It then consults polkit to determine whether the client should be permitted to execute the requested actions.
守护程序的工作原理是将类似 Upgrade()
的 D-Bus 方法调用转换为 os_authorize_method
中的政策工具包操作。然后,它会查询政策工具包以确定客户端是否被允许执行请求的操作。
We ship a base policy file which provide actions which should be allowed (see src/daemon/org.projectatomic.rpmostree1.policy
).
我们提供一个基本策略文件,其中包含应该允许的操作(请参阅 src/daemon/org.projectatomic.rpmostree1.policy
)。
Some distros may enhance this policy by shipping rules which dynamically calculate authorization based on e.g. group membership. For example, in Fedora: org.projectatomic.rpmostree1.rules
.
一些发行版可能通过提供动态计算授权的规则来增强此策略,例如基于组成员身份。例如,在 Fedora 中: org.projectatomic.rpmostree1.rules
。
Modifying the D-Bus API
修改 D-Bus API
Once a D-Bus API is stable, its signature cannot be modified because it would break other D-Bus clients. This is why many methods have a catch-all options
parameter which allows for extending the API without changing its signature.
一旦 D-Bus API 稳定,其签名就不能被修改,因为这会破坏其他 D-Bus 客户端。这就是为什么许多方法有一个捕获所有 options
参数,允许在不改变其签名的情况下扩展 API。
When adding new APIs, it’s OK to have separate arguments for each parameter considered essential to the operation, while keeping “auxiliary” parameters in an options
parameter (such as whether to reboot or not).
在添加新的 API 时,可以为每个被视为操作必要的参数设置单独的参数,同时将“辅助”参数放在一个 options
参数中(例如是否重新启动)。