[libvirt] [PATCH 0/3] Support changing user passwords in the guest

The guest-set-user-password command was added to qemu-agent in the 2.3.0 release by Daniel Berrange (some of you might have heard of him): commit 215a2771a7b6b29037ee8deba484815d816b6fdd qga: add guest-set-user-password command http://git.qemu.org/?p=qemu.git;a=commitdiff;h=215a277 This mini-series introduces a libvirt API, set_password ACL, a virsh command and wires up the API in the QEMU driver. Any bikesh^Wsuggestions regarding the API naming and the order of the virsh parameters are welcome. Ján Tomko (3): Introduce virDomainSetUserPassword API virsh: add set-user-password command qemu: wire up virDomainSetUserPassword include/libvirt/libvirt-domain.h | 9 +++++ src/access/viraccessperm.c | 2 +- src/access/viraccessperm.h | 6 ++++ src/driver-hypervisor.h | 7 ++++ src/libvirt-domain.c | 47 +++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++ src/qemu/qemu_agent.c | 39 +++++++++++++++++++++ src/qemu/qemu_agent.h | 4 +++ src/qemu/qemu_driver.c | 55 +++++++++++++++++++++++++++++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 15 +++++++- src/remote_protocol-structs | 7 ++++ tools/virsh-domain.c | 76 ++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 11 ++++++ 14 files changed, 282 insertions(+), 2 deletions(-) -- 2.0.5

For setting passwords of users inside the domain. With the VIR_DOMAIN_PASSWORD_CRYPTED flag set, the password is assumed to be already encrypted by crypt(3). https://bugzilla.redhat.com/show_bug.cgi?id=1174177 --- include/libvirt/libvirt-domain.h | 9 ++++++++ src/access/viraccessperm.c | 2 +- src/access/viraccessperm.h | 6 +++++ src/driver-hypervisor.h | 7 ++++++ src/libvirt-domain.c | 47 ++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 15 ++++++++++++- src/remote_protocol-structs | 7 ++++++ 9 files changed, 97 insertions(+), 2 deletions(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 0f465b9..b8e803d 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -3818,4 +3818,13 @@ int virDomainInterfaceAddresses(virDomainPtr dom, void virDomainInterfaceFree(virDomainInterfacePtr iface); +typedef enum { + VIR_DOMAIN_PASSWORD_CRYPTED = 1 << 0, /* the password is crypted by crypt(3) */ +} virDomainSetUserPasswordFlags; + +int virDomainSetUserPassword(virDomainPtr dom, + const char *user, + const char *password, + unsigned int flags); + #endif /* __VIR_LIBVIRT_DOMAIN_H__ */ diff --git a/src/access/viraccessperm.c b/src/access/viraccessperm.c index 9007186..0f58290 100644 --- a/src/access/viraccessperm.c +++ b/src/access/viraccessperm.c @@ -43,7 +43,7 @@ VIR_ENUM_IMPL(virAccessPermDomain, "fs_trim", "fs_freeze", "block_read", "block_write", "mem_read", "open_graphics", "open_device", "screenshot", - "open_namespace", "set_time"); + "open_namespace", "set_time", "set_password"); VIR_ENUM_IMPL(virAccessPermInterface, VIR_ACCESS_PERM_INTERFACE_LAST, diff --git a/src/access/viraccessperm.h b/src/access/viraccessperm.h index 8ccbbad..0acd156 100644 --- a/src/access/viraccessperm.h +++ b/src/access/viraccessperm.h @@ -300,6 +300,12 @@ typedef enum { */ VIR_ACCESS_PERM_DOMAIN_SET_TIME, + /** + * @desc: Set password of the domain's account + * @message: Setting the domain accounts' password requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_SET_PASSWORD, + VIR_ACCESS_PERM_DOMAIN_LAST, } virAccessPermDomain; diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index 8b8d031..3275343 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -1201,6 +1201,12 @@ typedef int unsigned int source, unsigned int flags); +typedef int +(*virDrvDomainSetUserPassword)(virDomainPtr dom, + const char *user, + const char *password, + unsigned int flags); + typedef struct _virHypervisorDriver virHypervisorDriver; typedef virHypervisorDriver *virHypervisorDriverPtr; @@ -1430,6 +1436,7 @@ struct _virHypervisorDriver { virDrvNodeAllocPages nodeAllocPages; virDrvDomainGetFSInfo domainGetFSInfo; virDrvDomainInterfaceAddresses domainInterfaceAddresses; + virDrvDomainSetUserPassword domainSetUserPassword; }; diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index d467758..c4e2345 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11001,6 +11001,53 @@ virDomainSetTime(virDomainPtr dom, } +/** + * virDomainSetUserPassword: + * @dom: a domain object + * @user: the username that will get a new password + * @password: the password to set + * @flags: bitwise-OR of virDomainSetUserPasswordFlags + * + * Sets the @user password to the value specified by @password. + * If @flags contain VIR_DOMAIN_PASSWORD_CRYPTED, the password + * is assumed to be crypted by crypt(3). + * + * Please note that some hypervisors may require guest agent to + * be configured and running in order to be able to run this API. + * + * Returns 0 on success, -1 otherwise. + */ +int +virDomainSetUserPassword(virDomainPtr dom, + const char *user, + const char *password, + unsigned int flags) +{ + VIR_DOMAIN_DEBUG(dom, "user=%s, password=%s, flags=%x", + NULLSTR(user), NULLSTR(password), flags); + + virResetLastError(); + + virCheckDomainReturn(dom, -1); + virCheckReadOnlyGoto(dom->conn->flags, error); + virCheckNonNullArgGoto(user, error); + virCheckNonNullArgGoto(password, error); + + if (dom->conn->driver->domainSetUserPassword) { + int ret = dom->conn->driver->domainSetUserPassword(dom, user, password, + flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(dom->conn); + return -1; +} + /** * virConnectGetDomainCapabilities: diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index ef3d2f0..716dd2f 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -710,4 +710,9 @@ LIBVIRT_1.2.15 { virDomainDelIOThread; } LIBVIRT_1.2.14; +LIBVIRT_1.2.16 { + global: + virDomainSetUserPassword; +} LIBVIRT_1.2.15; + # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 31417e8..dd8dab6 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -8389,6 +8389,7 @@ static virHypervisorDriver hypervisor_driver = { .nodeAllocPages = remoteNodeAllocPages, /* 1.2.9 */ .domainGetFSInfo = remoteDomainGetFSInfo, /* 1.2.11 */ .domainInterfaceAddresses = remoteDomainInterfaceAddresses, /* 1.2.14 */ + .domainSetUserPassword = remoteDomainSetUserPassword, /* 1.2.16 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 49b7ddd..9f1be6b 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3223,6 +3223,13 @@ struct remote_domain_interface_addresses_ret { remote_domain_interface ifaces<REMOTE_DOMAIN_INTERFACE_MAX>; }; +struct remote_domain_set_user_password_args { + remote_nonnull_domain dom; + remote_string user; + remote_string password; + unsigned int flags; +}; + /*----- Protocol. -----*/ @@ -5683,5 +5690,11 @@ enum remote_procedure { * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ - REMOTE_PROC_DOMAIN_DEL_IOTHREAD = 356 + REMOTE_PROC_DOMAIN_DEL_IOTHREAD = 356, + + /** + * @generate:both + * @acl: domain:set_password + */ + REMOTE_PROC_DOMAIN_SET_USER_PASSWORD = 357 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 116b572..48c3bd8 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2678,6 +2678,12 @@ struct remote_domain_interface_addresses_ret { remote_domain_interface * ifaces_val; } ifaces; }; +struct remote_domain_set_user_password_args { + remote_nonnull_domain dom; + remote_string user; + remote_string password; + u_int flags; +}; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN = 1, REMOTE_PROC_CONNECT_CLOSE = 2, @@ -3035,4 +3041,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_ADDED = 354, REMOTE_PROC_DOMAIN_ADD_IOTHREAD = 355, REMOTE_PROC_DOMAIN_DEL_IOTHREAD = 356, + REMOTE_PROC_DOMAIN_SET_USER_PASSWORD = 357, }; -- 2.0.5

On Mon, May 18, 2015 at 02:43:48PM +0200, Ján Tomko wrote:
For setting passwords of users inside the domain.
With the VIR_DOMAIN_PASSWORD_CRYPTED flag set, the password is assumed to be already encrypted by crypt(3).
https://bugzilla.redhat.com/show_bug.cgi?id=1174177 --- include/libvirt/libvirt-domain.h | 9 ++++++++ src/access/viraccessperm.c | 2 +- src/access/viraccessperm.h | 6 +++++ src/driver-hypervisor.h | 7 ++++++ src/libvirt-domain.c | 47 ++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 15 ++++++++++++- src/remote_protocol-structs | 7 ++++++ 9 files changed, 97 insertions(+), 2 deletions(-)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 0f465b9..b8e803d 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -3818,4 +3818,13 @@ int virDomainInterfaceAddresses(virDomainPtr dom,
void virDomainInterfaceFree(virDomainInterfacePtr iface);
+typedef enum { + VIR_DOMAIN_PASSWORD_CRYPTED = 1 << 0, /* the password is crypted by crypt(3) */
nit-pick, is crypted by the method that is required by the guest OS. This may or may not be the same as what's provided by the crypt(3) method in the host. IOW, the user/mgmt app needs to know what the guest OS mandates in this area. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Mon, May 18, 2015 at 02:43:48PM +0200, Ján Tomko wrote:
For setting passwords of users inside the domain.
With the VIR_DOMAIN_PASSWORD_CRYPTED flag set, the password is assumed to be already encrypted by crypt(3).
https://bugzilla.redhat.com/show_bug.cgi?id=1174177 --- include/libvirt/libvirt-domain.h | 9 ++++++++ src/access/viraccessperm.c | 2 +- src/access/viraccessperm.h | 6 +++++ src/driver-hypervisor.h | 7 ++++++ src/libvirt-domain.c | 47 ++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 15 ++++++++++++- src/remote_protocol-structs | 7 ++++++ 9 files changed, 97 insertions(+), 2 deletions(-)
ACK if you address the nitpick about crypt() in the API docs. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Expose the virDomainSetUserPassword API in virsh: virsh set-user-password dom 123456 user For root, the username can be omitted: virsh set-user-password dom 123456 --- tools/virsh-domain.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 11 ++++++++ 2 files changed, 87 insertions(+) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 20f8c75..a654623 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -5381,6 +5381,76 @@ cmdScreenshot(vshControl *ctl, const vshCmd *cmd) } /* + * "set-user-password" command + */ +static const vshCmdInfo info_set_user_password[] = { + {.name = "help", + .data = N_("set the user password inside the domain") + }, + {.name = "desc", + .data = N_("changes the password of the specified user inside the domain") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_set_user_password[] = { + {.name = "domain", + .type = VSH_OT_DATA, + .flags = VSH_OFLAG_REQ, + .help = N_("domain name, id or uuid") + }, + {.name = "password", + .type = VSH_OT_DATA, + .flags = VSH_OFLAG_REQ, + .help = N_("the new password") + }, + {.name = "user", + .type = VSH_OT_STRING, + .help = N_("the username") + }, + {.name = "crypted", + .type = VSH_OT_BOOL, + .help = N_("the password is already crypted") + }, + {.name = NULL} +}; + +static bool +cmdSetUserPassword(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + const char *name; + const char *password = NULL; + const char *user = NULL; + unsigned int flags = 0; + bool ret = false; + + if (vshCommandOptBool(cmd, "crypted")) + flags = VIR_DOMAIN_PASSWORD_CRYPTED; + + if (vshCommandOptStringReq(ctl, cmd, "user", &user) < 0) + return false; + + if (vshCommandOptStringReq(ctl, cmd, "password", &password) < 0) + return false; + + if (!user) + user = "root"; + + if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + return false; + + if (virDomainSetUserPassword(dom, user, password, flags) < 0) + goto cleanup; + + vshPrint(ctl, _("Password set successfully for %s in %s"), user, name); + ret = true; + + cleanup: + virDomainFree(dom); + return ret; +} +/* * "resume" command */ static const vshCmdInfo info_resume[] = { @@ -13159,6 +13229,12 @@ const vshCmdDef domManagementCmds[] = { .info = info_screenshot, .flags = 0 }, + {.name = "set-user-password", + .handler = cmdSetUserPassword, + .opts = opts_set_user_password, + .info = info_set_user_password, + .flags = 0 + }, {.name = "setmaxmem", .handler = cmdSetmaxmem, .opts = opts_setmaxmem, diff --git a/tools/virsh.pod b/tools/virsh.pod index 1bb655b..9bd52f2 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -2015,6 +2015,17 @@ the value from the host, use the B<virsh memtune> command. In order to view the current memory in use and the maximum value allowed to set memory, use the B<virsh dominfo> command. +=item B<set-user-password> I<domain> I<password> [I<user>] [I<--crypted>] + +Set the password for the I<user> account in the guest domain. +If the user is omitted, root is assumed by virsh. + +If I<--crypted> is specified, the password is assumed to be crypted +already by crypt(3). + +For QEMU/KVM, this requires the guest agent to be configured +and running. + =item B<setmaxmem> I<domain> B<size> [[I<--config>] [I<--live>] | [I<--current>]] -- 2.0.5

On Mon, May 18, 2015 at 02:43:49PM +0200, Ján Tomko wrote:
Expose the virDomainSetUserPassword API in virsh: virsh set-user-password dom 123456 user
For root, the username can be omitted: virsh set-user-password dom 123456 --- tools/virsh-domain.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 11 ++++++++ 2 files changed, 87 insertions(+)
+static bool +cmdSetUserPassword(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + const char *name; + const char *password = NULL; + const char *user = NULL; + unsigned int flags = 0; + bool ret = false; + + if (vshCommandOptBool(cmd, "crypted")) + flags = VIR_DOMAIN_PASSWORD_CRYPTED; + + if (vshCommandOptStringReq(ctl, cmd, "user", &user) < 0) + return false; + + if (vshCommandOptStringReq(ctl, cmd, "password", &password) < 0) + return false; + + if (!user) + user = "root";
This presumes the guest is UNIX. I'd be inclined to have user always be required, and also have user specified before the password, as that seems slightly more common eg htpasswd tools Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 20.05.2015 14:30, Daniel P. Berrange wrote:
On Mon, May 18, 2015 at 02:43:49PM +0200, Ján Tomko wrote:
Expose the virDomainSetUserPassword API in virsh: virsh set-user-password dom 123456 user
For root, the username can be omitted: virsh set-user-password dom 123456 --- tools/virsh-domain.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 11 ++++++++ 2 files changed, 87 insertions(+)
+static bool +cmdSetUserPassword(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + const char *name; + const char *password = NULL; + const char *user = NULL; + unsigned int flags = 0; + bool ret = false; + + if (vshCommandOptBool(cmd, "crypted")) + flags = VIR_DOMAIN_PASSWORD_CRYPTED; + + if (vshCommandOptStringReq(ctl, cmd, "user", &user) < 0) + return false; + + if (vshCommandOptStringReq(ctl, cmd, "password", &password) < 0) + return false; + + if (!user) + user = "root";
This presumes the guest is UNIX. I'd be inclined to have user always be required, and also have user specified before the password, as that seems slightly more common eg htpasswd tools
Agreed. ACK if you fix it. Michal

Base-64 encode the password and pass it to the guest agent via the 'guest-set-user-password' command. https://bugzilla.redhat.com/show_bug.cgi?id=1174177 --- src/qemu/qemu_agent.c | 39 +++++++++++++++++++++++++++++++++++ src/qemu/qemu_agent.h | 4 ++++ src/qemu/qemu_driver.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index fc23c41..71aed64 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -42,6 +42,7 @@ #include "virtime.h" #include "virobject.h" #include "virstring.h" +#include "base64.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -2117,3 +2118,41 @@ qemuAgentGetInterfaces(qemuAgentPtr mon, goto cleanup; } + + +int +qemuAgentSetUserPassword(qemuAgentPtr mon, + const char *user, + const char *password, + bool crypted) +{ + int ret = -1; + virJSONValuePtr cmd = NULL; + virJSONValuePtr reply = NULL; + char *password64 = NULL; + + base64_encode_alloc(password, strlen(password), &password64); + if (!password64) { + virReportOOMError(); + goto cleanup; + } + + if (!(cmd = qemuAgentMakeCommand("guest-set-user-password", + "b:crypted", crypted, + "s:username", user, + "s:password", password64, + NULL))) + goto cleanup; + + if (qemuAgentCommand(mon, cmd, &reply, true, + VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0) + goto cleanup; + + ret = 0; + + cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + VIR_FREE(password64); + return ret; +} diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 988228b..7cbf8eb 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -114,4 +114,8 @@ int qemuAgentSetTime(qemuAgentPtr mon, int qemuAgentGetInterfaces(qemuAgentPtr mon, virDomainInterfacePtr **ifaces); +int qemuAgentSetUserPassword(qemuAgentPtr mon, + const char *user, + const char *password, + bool crypted); #endif /* __QEMU_AGENT_H__ */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2668011..6c7bc86 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20124,6 +20124,60 @@ qemuGetDHCPInterfaces(virDomainPtr dom, goto cleanup; } + +static int +qemuDomainSetUserPassword(virDomainPtr dom, + const char *user, + const char *password, + unsigned int flags) +{ + virQEMUDriverPtr driver = dom->conn->privateData; + qemuDomainObjPrivatePtr priv; + virDomainObjPtr vm; + int ret = -1; + int rv; + + virCheckFlags(VIR_DOMAIN_PASSWORD_CRYPTED, -1); + + if (!(vm = qemuDomObjFromDomain(dom))) + return ret; + + if (virDomainSetUserPasswordEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + priv = vm->privateData; + + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) { + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto endjob; + } + + if (!qemuDomainAgentAvailable(vm, true)) + goto endjob; + + qemuDomainObjEnterAgent(vm); + rv = qemuAgentSetUserPassword(priv->agent, user, password, + flags & VIR_DOMAIN_PASSWORD_CRYPTED); + qemuDomainObjExitAgent(vm); + + if (rv < 0) + goto endjob; + + ret = 0; + + endjob: + qemuDomainObjEndJob(driver, vm); + + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + + static virHypervisorDriver qemuHypervisorDriver = { .name = QEMU_DRIVER_NAME, .connectOpen = qemuConnectOpen, /* 0.2.0 */ @@ -20330,6 +20384,7 @@ static virHypervisorDriver qemuHypervisorDriver = { .nodeAllocPages = qemuNodeAllocPages, /* 1.2.9 */ .domainGetFSInfo = qemuDomainGetFSInfo, /* 1.2.11 */ .domainInterfaceAddresses = qemuDomainInterfaceAddresses, /* 1.2.14 */ + .domainSetUserPassword = qemuDomainSetUserPassword, /* 1.2.16 */ }; -- 2.0.5

On 18.05.2015 14:43, Ján Tomko wrote:
Base-64 encode the password and pass it to the guest agent via the 'guest-set-user-password' command.
https://bugzilla.redhat.com/show_bug.cgi?id=1174177 --- src/qemu/qemu_agent.c | 39 +++++++++++++++++++++++++++++++++++ src/qemu/qemu_agent.h | 4 ++++ src/qemu/qemu_driver.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2668011..6c7bc86 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20124,6 +20124,60 @@ qemuGetDHCPInterfaces(virDomainPtr dom, goto cleanup; }
+ +static int +qemuDomainSetUserPassword(virDomainPtr dom, + const char *user, + const char *password, + unsigned int flags) +{ + virQEMUDriverPtr driver = dom->conn->privateData; + qemuDomainObjPrivatePtr priv; + virDomainObjPtr vm; + int ret = -1; + int rv; +
I failed to see how @rv is different to @ret.
+ virCheckFlags(VIR_DOMAIN_PASSWORD_CRYPTED, -1); + + if (!(vm = qemuDomObjFromDomain(dom))) + return ret; + + if (virDomainSetUserPasswordEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + priv = vm->privateData; + + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) { + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto endjob; + } + + if (!qemuDomainAgentAvailable(vm, true)) + goto endjob; + + qemuDomainObjEnterAgent(vm); + rv = qemuAgentSetUserPassword(priv->agent, user, password, + flags & VIR_DOMAIN_PASSWORD_CRYPTED); + qemuDomainObjExitAgent(vm); + + if (rv < 0) + goto endjob; + + ret = 0; + + endjob: + qemuDomainObjEndJob(driver, vm); + + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + +
ACK though. Michal

On Mon, May 18, 2015 at 02:43:47PM +0200, Ján Tomko wrote:
The guest-set-user-password command was added to qemu-agent in the 2.3.0 release by Daniel Berrange (some of you might have heard of him):
commit 215a2771a7b6b29037ee8deba484815d816b6fdd qga: add guest-set-user-password command http://git.qemu.org/?p=qemu.git;a=commitdiff;h=215a277
This mini-series introduces a libvirt API, set_password ACL, a virsh command and wires up the API in the QEMU driver.
Any bikesh^Wsuggestions regarding the API naming and the order of the virsh parameters are welcome.
Ján Tomko (3): Introduce virDomainSetUserPassword API virsh: add set-user-password command qemu: wire up virDomainSetUserPassword
I have removed the linux-specific bits (crypt(3), defaulting to root), switched the order of virsh parameters and pushed the series. Thank you for the reviews. Jan
participants (3)
-
Daniel P. Berrange
-
Ján Tomko
-
Michal Privoznik