searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

深入了解virsh setuserpassword流程

2024-12-06 09:31:07
2
0
  1. virsh setuserpassword 的基本功能
    image.png
  • <domain>:虚拟机名称或 UUID。
  • <username>:虚拟机内需要修改密码的用户名。
  • <password>:新密码(传递时会被加密)。
  • --crypt(可选):指示密码已使用合适算法加密(如 SHA-256)。

该命令通过 libvirt 与虚拟机的管理工具(如 QEMU 或其他 hypervisor)交互,最终调用虚拟机内的 QEMU Guest Agent 来完成密码修改。

2. 流程概览

  1. 命令解析与参数处理:virsh 作为 libvirt 的 CLI 工具,接收并解析命令行参数,调用 libvirt 的 virDomainSetUserPassword API。
  2. API 调用与 XML-RPC 传递: libvirt 的 virDomainSetUserPassword API 将请求封装成内部通信协议(如 RPC),发送到 libvirtd 守护进程。
  3. 守护进程处理: libvirtd 解析请求,匹配虚拟机域信息,找到对应 hypervisor 的驱动程序(如 QEMU)。
  4. 与虚拟机通信: libvirt 通过 hypervisor 的工具(如 QEMU Guest Agent)与虚拟机内部通信,传递密码修改请求。
  5. QEMU Guest Agent 执行: QEMU Guest Agent 在虚拟机内执行操作,修改指定用户的密码,并返回结果。

3. 源码解析

以下以 libvirt 源码为例,逐步分析 virsh setuserpassword 的内部实现。

3.1 virsh 的参数解析

源码位置:tools/virsh-domain.c

virsh setuserpassword 命令对应的实现:
image.png

解析后,virDomainSetUserPassword 函数被调用,负责将请求传递给 libvirtd。

3.2 libvirt API 的实现

源码位置:src/libvirt-domain.c

virDomainSetUserPassword 的实现:
image.png
这一步将请求转交给连接对象(virConnectPtr)所关联的驱动程序。对于 QEMU hypervisor,最终会调用 QEMU 驱动。

3.3 QEMU 驱动处理

源码位置:src/qemu/qemu_driver.c

QEMU 驱动实现 domainSetUserPassword
image.png
此处检查 QEMU Guest Agent 是否启用,并调用 qemuAgentSetUserPassword 发送请求。

3.4 与 QEMU Guest Agent 通信

源码位置:src/qemu/qemu_agent.c

qemuAgentSetUserPassword 的实现:
image.png
QEMU Guest Agent 使用 JSON 格式命令与虚拟机内的代理进程通信。例如,构建的命令可能如下:
image.png

3.5 QEMU Guest Agent 的操作

在虚拟机内,QEMU Guest Agent 接收到上述 JSON 命令后,调用系统工具(如 passwd 或其他用户管理命令)完成密码修改,并返回结果。
virsh setuserpassword 是 libvirt 提供的一个命令,用于在运行的虚拟机内部修改用户的密码。这一命令触发了 libvirt 的多层逻辑,包括 API 调用、主机-虚拟机通信机制、以及对 QEMU Guest Agent 的交互。以下是深入了解其工作流程及源码的详细分析。


1. virsh setuserpassword 的基本功能

命令格式:

bash
<button class="flex gap-1 items-center py-1"><svg width="24" height="24" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制代码</button>
virsh setuserpassword <domain> <username> <password> [--crypt]
  • <domain>:虚拟机名称或 UUID。
  • <username>:虚拟机内需要修改密码的用户名。
  • <password>:新密码(传递时会被加密)。
  • --crypt(可选):指示密码已使用合适算法加密(如 SHA-256)。

该命令通过 libvirt 与虚拟机的管理工具(如 QEMU 或其他 hypervisor)交互,最终调用虚拟机内的 QEMU Guest Agent 来完成密码修改。


2. 流程概览

  1. 命令解析与参数处理:virsh 作为 libvirt 的 CLI 工具,接收并解析命令行参数,调用 libvirt 的 virDomainSetUserPassword API。
  2. API 调用与 XML-RPC 传递: libvirt 的 virDomainSetUserPassword API 将请求封装成内部通信协议(如 RPC),发送到 libvirtd 守护进程。
  3. 守护进程处理: libvirtd 解析请求,匹配虚拟机域信息,找到对应 hypervisor 的驱动程序(如 QEMU)。
  4. 与虚拟机通信: libvirt 通过 hypervisor 的工具(如 QEMU Guest Agent)与虚拟机内部通信,传递密码修改请求。
  5. QEMU Guest Agent 执行: QEMU Guest Agent 在虚拟机内执行操作,修改指定用户的密码,并返回结果。

3. 源码解析

以下以 libvirt 源码为例,逐步分析 virsh setuserpassword 的内部实现。

3.1 virsh 的参数解析

源码位置:tools/virsh-domain.c

virsh setuserpassword 命令对应的实现:

c
<button class="flex gap-1 items-center py-1"><svg width="24" height="24" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制代码</button>
static bool cmdSetUserPassword(vshControl *ctl, const vshCmd *cmd) { const char *domName; const char *user; const char *password; bool crypt = false; domName = vshCommandOptString(cmd, "domain", NULL); user = vshCommandOptString(cmd, "user", NULL); password = vshCommandOptString(cmd, "password", NULL); crypt = vshCommandOptBool(cmd, "crypt"); // 调用 libvirt API if (virDomainSetUserPassword(domName, user, password, crypt, 0) < 0) { vshError(ctl, _("Failed to set user password")); return false; } return true; }

解析后,virDomainSetUserPassword 函数被调用,负责将请求传递给 libvirtd。


3.2 libvirt API 的实现

源码位置:src/libvirt-domain.c

virDomainSetUserPassword 的实现:

c
<button class="flex gap-1 items-center py-1"><svg width="24" height="24" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制代码</button>
int virDomainSetUserPassword(virDomainPtr domain, const char *user, const char *password, unsigned int flags) { virConnectPtr conn; int ret; VIR_DOMAIN_DEBUG(domain, "user=%s, flags=%x", user, flags); conn = domain->conn; ret = conn->driver->domainSetUserPassword(domain, user, password, flags); return ret; }

这一步将请求转交给连接对象(virConnectPtr)所关联的驱动程序。对于 QEMU hypervisor,最终会调用 QEMU 驱动。


3.3 QEMU 驱动处理

源码位置:src/qemu/qemu_driver.c

QEMU 驱动实现 domainSetUserPassword

c
<button class="flex gap-1 items-center py-1"><svg width="24" height="24" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制代码</button>
static int qemuDomainSetUserPassword(virDomainPtr domain, const char *user, const char *password, unsigned int flags) { qemuDomainObjPrivatePtr priv; virQEMUDriverPtr driver; priv = QEMU_DOMAIN_PRIVATE(domain); driver = priv->driver; if (!priv->agent) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("QEMU Guest Agent is not available")); return -1; } // 调用 QEMU Guest Agent 发送命令 return qemuAgentSetUserPassword(priv->agent, user, password, flags); }

此处检查 QEMU Guest Agent 是否启用,并调用 qemuAgentSetUserPassword 发送请求。


3.4 与 QEMU Guest Agent 通信

源码位置:src/qemu/qemu_agent.c

qemuAgentSetUserPassword 的实现:

c
<button class="flex gap-1 items-center py-1"><svg width="24" height="24" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制代码</button>
int qemuAgentSetUserPassword(qemuAgentPtr agent, const char *user, const char *password, unsigned int flags) { qemuAgentCommand agentCmd; char *cmd; // 构建 QEMU Guest Agent JSON 命令 cmd = qemuAgentMakeCommand("guest-set-user-password", "s:user", user, "s:password", password, "b:crypted", crypt); // 发送命令到虚拟机内 return qemuAgentCommandRun(agent, cmd, NULL); }

QEMU Guest Agent 使用 JSON 格式命令与虚拟机内的代理进程通信。例如,构建的命令可能如下:

json
<button class="flex gap-1 items-center py-1"><svg width="24" height="24" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制代码</button>
{ "execute": "guest-set-user-password", "arguments": { "user": "testuser", "password": "newpassword", "crypted": false } }

3.5 QEMU Guest Agent 的操作

在虚拟机内,QEMU Guest Agent 接收到上述 JSON 命令后,调用系统工具(如 passwd 或其他用户管理命令)完成密码修改,并返回结果。


4. 流程总结

  1. virsh 命令行工具: 解析用户输入,调用 libvirt API。
  2. libvirt API: 封装请求,交由对应 hypervisor 驱动(如 QEMU)。
  3. QEMU 驱动: 调用 QEMU Guest Agent,通过 JSON 命令与虚拟机内部通信。
  4. QEMU Guest Agent: 执行具体的用户管理操作,并返回执行结果。
0条评论
作者已关闭评论
郑****娜
8文章数
0粉丝数
郑****娜
8 文章 | 0 粉丝
原创

深入了解virsh setuserpassword流程

2024-12-06 09:31:07
2
0
  1. virsh setuserpassword 的基本功能
    image.png
  • <domain>:虚拟机名称或 UUID。
  • <username>:虚拟机内需要修改密码的用户名。
  • <password>:新密码(传递时会被加密)。
  • --crypt(可选):指示密码已使用合适算法加密(如 SHA-256)。

该命令通过 libvirt 与虚拟机的管理工具(如 QEMU 或其他 hypervisor)交互,最终调用虚拟机内的 QEMU Guest Agent 来完成密码修改。

2. 流程概览

  1. 命令解析与参数处理:virsh 作为 libvirt 的 CLI 工具,接收并解析命令行参数,调用 libvirt 的 virDomainSetUserPassword API。
  2. API 调用与 XML-RPC 传递: libvirt 的 virDomainSetUserPassword API 将请求封装成内部通信协议(如 RPC),发送到 libvirtd 守护进程。
  3. 守护进程处理: libvirtd 解析请求,匹配虚拟机域信息,找到对应 hypervisor 的驱动程序(如 QEMU)。
  4. 与虚拟机通信: libvirt 通过 hypervisor 的工具(如 QEMU Guest Agent)与虚拟机内部通信,传递密码修改请求。
  5. QEMU Guest Agent 执行: QEMU Guest Agent 在虚拟机内执行操作,修改指定用户的密码,并返回结果。

3. 源码解析

以下以 libvirt 源码为例,逐步分析 virsh setuserpassword 的内部实现。

3.1 virsh 的参数解析

源码位置:tools/virsh-domain.c

virsh setuserpassword 命令对应的实现:
image.png

解析后,virDomainSetUserPassword 函数被调用,负责将请求传递给 libvirtd。

3.2 libvirt API 的实现

源码位置:src/libvirt-domain.c

virDomainSetUserPassword 的实现:
image.png
这一步将请求转交给连接对象(virConnectPtr)所关联的驱动程序。对于 QEMU hypervisor,最终会调用 QEMU 驱动。

3.3 QEMU 驱动处理

源码位置:src/qemu/qemu_driver.c

QEMU 驱动实现 domainSetUserPassword
image.png
此处检查 QEMU Guest Agent 是否启用,并调用 qemuAgentSetUserPassword 发送请求。

3.4 与 QEMU Guest Agent 通信

源码位置:src/qemu/qemu_agent.c

qemuAgentSetUserPassword 的实现:
image.png
QEMU Guest Agent 使用 JSON 格式命令与虚拟机内的代理进程通信。例如,构建的命令可能如下:
image.png

3.5 QEMU Guest Agent 的操作

在虚拟机内,QEMU Guest Agent 接收到上述 JSON 命令后,调用系统工具(如 passwd 或其他用户管理命令)完成密码修改,并返回结果。
virsh setuserpassword 是 libvirt 提供的一个命令,用于在运行的虚拟机内部修改用户的密码。这一命令触发了 libvirt 的多层逻辑,包括 API 调用、主机-虚拟机通信机制、以及对 QEMU Guest Agent 的交互。以下是深入了解其工作流程及源码的详细分析。


1. virsh setuserpassword 的基本功能

命令格式:

bash
<button class="flex gap-1 items-center py-1"><svg width="24" height="24" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制代码</button>
virsh setuserpassword <domain> <username> <password> [--crypt]
  • <domain>:虚拟机名称或 UUID。
  • <username>:虚拟机内需要修改密码的用户名。
  • <password>:新密码(传递时会被加密)。
  • --crypt(可选):指示密码已使用合适算法加密(如 SHA-256)。

该命令通过 libvirt 与虚拟机的管理工具(如 QEMU 或其他 hypervisor)交互,最终调用虚拟机内的 QEMU Guest Agent 来完成密码修改。


2. 流程概览

  1. 命令解析与参数处理:virsh 作为 libvirt 的 CLI 工具,接收并解析命令行参数,调用 libvirt 的 virDomainSetUserPassword API。
  2. API 调用与 XML-RPC 传递: libvirt 的 virDomainSetUserPassword API 将请求封装成内部通信协议(如 RPC),发送到 libvirtd 守护进程。
  3. 守护进程处理: libvirtd 解析请求,匹配虚拟机域信息,找到对应 hypervisor 的驱动程序(如 QEMU)。
  4. 与虚拟机通信: libvirt 通过 hypervisor 的工具(如 QEMU Guest Agent)与虚拟机内部通信,传递密码修改请求。
  5. QEMU Guest Agent 执行: QEMU Guest Agent 在虚拟机内执行操作,修改指定用户的密码,并返回结果。

3. 源码解析

以下以 libvirt 源码为例,逐步分析 virsh setuserpassword 的内部实现。

3.1 virsh 的参数解析

源码位置:tools/virsh-domain.c

virsh setuserpassword 命令对应的实现:

c
<button class="flex gap-1 items-center py-1"><svg width="24" height="24" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制代码</button>
static bool cmdSetUserPassword(vshControl *ctl, const vshCmd *cmd) { const char *domName; const char *user; const char *password; bool crypt = false; domName = vshCommandOptString(cmd, "domain", NULL); user = vshCommandOptString(cmd, "user", NULL); password = vshCommandOptString(cmd, "password", NULL); crypt = vshCommandOptBool(cmd, "crypt"); // 调用 libvirt API if (virDomainSetUserPassword(domName, user, password, crypt, 0) < 0) { vshError(ctl, _("Failed to set user password")); return false; } return true; }

解析后,virDomainSetUserPassword 函数被调用,负责将请求传递给 libvirtd。


3.2 libvirt API 的实现

源码位置:src/libvirt-domain.c

virDomainSetUserPassword 的实现:

c
<button class="flex gap-1 items-center py-1"><svg width="24" height="24" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制代码</button>
int virDomainSetUserPassword(virDomainPtr domain, const char *user, const char *password, unsigned int flags) { virConnectPtr conn; int ret; VIR_DOMAIN_DEBUG(domain, "user=%s, flags=%x", user, flags); conn = domain->conn; ret = conn->driver->domainSetUserPassword(domain, user, password, flags); return ret; }

这一步将请求转交给连接对象(virConnectPtr)所关联的驱动程序。对于 QEMU hypervisor,最终会调用 QEMU 驱动。


3.3 QEMU 驱动处理

源码位置:src/qemu/qemu_driver.c

QEMU 驱动实现 domainSetUserPassword

c
<button class="flex gap-1 items-center py-1"><svg width="24" height="24" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制代码</button>
static int qemuDomainSetUserPassword(virDomainPtr domain, const char *user, const char *password, unsigned int flags) { qemuDomainObjPrivatePtr priv; virQEMUDriverPtr driver; priv = QEMU_DOMAIN_PRIVATE(domain); driver = priv->driver; if (!priv->agent) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("QEMU Guest Agent is not available")); return -1; } // 调用 QEMU Guest Agent 发送命令 return qemuAgentSetUserPassword(priv->agent, user, password, flags); }

此处检查 QEMU Guest Agent 是否启用,并调用 qemuAgentSetUserPassword 发送请求。


3.4 与 QEMU Guest Agent 通信

源码位置:src/qemu/qemu_agent.c

qemuAgentSetUserPassword 的实现:

c
<button class="flex gap-1 items-center py-1"><svg width="24" height="24" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制代码</button>
int qemuAgentSetUserPassword(qemuAgentPtr agent, const char *user, const char *password, unsigned int flags) { qemuAgentCommand agentCmd; char *cmd; // 构建 QEMU Guest Agent JSON 命令 cmd = qemuAgentMakeCommand("guest-set-user-password", "s:user", user, "s:password", password, "b:crypted", crypt); // 发送命令到虚拟机内 return qemuAgentCommandRun(agent, cmd, NULL); }

QEMU Guest Agent 使用 JSON 格式命令与虚拟机内的代理进程通信。例如,构建的命令可能如下:

json
<button class="flex gap-1 items-center py-1"><svg width="24" height="24" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"><path fill-rule="evenodd" clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor"></path></svg>复制代码</button>
{ "execute": "guest-set-user-password", "arguments": { "user": "testuser", "password": "newpassword", "crypted": false } }

3.5 QEMU Guest Agent 的操作

在虚拟机内,QEMU Guest Agent 接收到上述 JSON 命令后,调用系统工具(如 passwd 或其他用户管理命令)完成密码修改,并返回结果。


4. 流程总结

  1. virsh 命令行工具: 解析用户输入,调用 libvirt API。
  2. libvirt API: 封装请求,交由对应 hypervisor 驱动(如 QEMU)。
  3. QEMU 驱动: 调用 QEMU Guest Agent,通过 JSON 命令与虚拟机内部通信。
  4. QEMU Guest Agent: 执行具体的用户管理操作,并返回执行结果。
文章来自个人专栏
软件开发问题记录
5 文章 | 1 订阅
0条评论
作者已关闭评论
作者已关闭评论
0
0