On Thu, Feb 11, 2010 at 02:31:37PM +0000, Daniel P. Berrange wrote: > The old text mode monitor prompts for a password when disks are > encrypted. This interactive approach doesn't work for JSON mode > monitor. Thus there is a new 'block_passwd' command that can be > used. > > * src/qemu/qemu_driver.c: Split out code for looking up a disk > secret from findVolumeQcowPassphrase, into a new method > getVolumeQcowPassphrase. Enhance qemuInitPasswords() to also > set the disk encryption password via the monitor > * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, > src/qemu/qemu_monitor_json.c, src/qemu/qemu_monitor_json.h, > src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h: Add > support for the 'block_passwd' monitor command. > --- > src/qemu/qemu_driver.c | 117 +++++++++++++++++++++++++++++------------- > src/qemu/qemu_monitor.c | 15 +++++ > src/qemu/qemu_monitor.h | 4 ++ > src/qemu/qemu_monitor_json.c | 33 ++++++++++++ > src/qemu/qemu_monitor_json.h | 4 ++ > src/qemu/qemu_monitor_text.c | 47 +++++++++++++++++ > src/qemu/qemu_monitor_text.h | 4 ++ > 7 files changed, 188 insertions(+), 36 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index 0d77d57..03d0f5f 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -694,51 +694,46 @@ qemuHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > } > > > -static virStorageEncryptionPtr > -findDomainDiskEncryption(virDomainObjPtr vm, > - const char *path) > +static virDomainDiskDefPtr > +findDomainDiskByPath(virDomainObjPtr vm, > + const char *path) > { > - bool seen_volume; > int i; > > - seen_volume = false; > for (i = 0; i < vm->def->ndisks; i++) { > virDomainDiskDefPtr disk; > > disk = vm->def->disks[i]; > - if (disk->src != NULL && STREQ(disk->src, path)) { > - seen_volume = true; > - if (disk->encryption != NULL) > - return disk->encryption; > - } > + if (disk->src != NULL && STREQ(disk->src, path)) > + return disk; > } > - if (seen_volume) > - qemuReportError(VIR_ERR_INVALID_DOMAIN, > - _("missing <encryption> for volume %s"), path); > - else > - qemuReportError(VIR_ERR_INTERNAL_ERROR, > - _("unexpected passphrase request for volume %s"), > - path); > + > + qemuReportError(VIR_ERR_INTERNAL_ERROR, > + _("no disk found with path %s"), > + path); > return NULL; > } > > - > static int > -findVolumeQcowPassphrase(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > - virConnectPtr conn, > - virDomainObjPtr vm, > - const char *path, > - char **secretRet, > - size_t *secretLen) > +getVolumeQcowPassphrase(virConnectPtr conn, > + virDomainDiskDefPtr disk, > + char **secretRet, > + size_t *secretLen) > { > - virStorageEncryptionPtr enc; > virSecretPtr secret; > char *passphrase; > unsigned char *data; > size_t size; > int ret = -1; > + virStorageEncryptionPtr enc; > > - virDomainObjLock(vm); > + if (!disk->encryption) { > + qemuReportError(VIR_ERR_INTERNAL_ERROR, > + _("disk %s does not have any encryption information"), > + disk->src); > + return -1; > + } > + enc = disk->encryption; > > if (!conn) { > qemuReportError(VIR_ERR_NO_SUPPORT, > @@ -754,16 +749,12 @@ findVolumeQcowPassphrase(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > goto cleanup; > } > > - enc = findDomainDiskEncryption(vm, path); > - if (enc == NULL) > - return -1; > - > if (enc->format != VIR_STORAGE_ENCRYPTION_FORMAT_QCOW || > enc->nsecrets != 1 || > enc->secrets[0]->type != > VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE) { > qemuReportError(VIR_ERR_INVALID_DOMAIN, > - _("invalid <encryption> for volume %s"), path); > + _("invalid <encryption> for volume %s"), disk->src); > goto cleanup; > } > > @@ -782,7 +773,7 @@ findVolumeQcowPassphrase(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > VIR_FREE(data); > qemuReportError(VIR_ERR_INVALID_SECRET, > _("format='qcow' passphrase for %s must not contain a " > - "'\\0'"), path); > + "'\\0'"), disk->src); > goto cleanup; > } > > @@ -804,8 +795,30 @@ findVolumeQcowPassphrase(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > ret = 0; > > cleanup: > - virDomainObjUnlock(vm); > + return ret; > +} > > +static int > +findVolumeQcowPassphrase(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > + virConnectPtr conn, > + virDomainObjPtr vm, > + const char *path, > + char **secretRet, > + size_t *secretLen) > +{ > + virDomainDiskDefPtr disk; > + int ret = -1; > + > + virDomainObjLock(vm); > + disk = findDomainDiskByPath(vm, path); > + > + if (!disk) > + goto cleanup; > + > + ret = getVolumeQcowPassphrase(conn, disk, secretRet, secretLen); > + > +cleanup: > + virDomainObjUnlock(vm); > return ret; > } > > @@ -1681,8 +1694,10 @@ qemudInitCpuAffinity(virDomainObjPtr vm) > > > static int > -qemuInitPasswords(struct qemud_driver *driver, > - virDomainObjPtr vm) { > +qemuInitPasswords(virConnectPtr conn, > + struct qemud_driver *driver, > + virDomainObjPtr vm, > + unsigned long long qemuCmdFlags) { > int ret = 0; > qemuDomainObjPrivatePtr priv = vm->privateData; > > @@ -1698,6 +1713,36 @@ qemuInitPasswords(struct qemud_driver *driver, > qemuDomainObjExitMonitorWithDriver(driver, vm); > } > > + if (ret < 0) > + goto cleanup; > + > + if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { > + int i; > + > + for (i = 0 ; i < vm->def->ndisks ; i++) { > + char *secret; > + size_t secretLen; > + > + if (!vm->def->disks[i]->encryption || > + !vm->def->disks[i]->src) > + continue; > + > + if (getVolumeQcowPassphrase(conn, > + vm->def->disks[i], > + &secret, &secretLen) < 0) > + goto cleanup; > + > + qemuDomainObjEnterMonitorWithDriver(driver, vm); > + ret = qemuMonitorSetDrivePassphrase(priv->mon, > + vm->def->disks[i]->info.alias, > + secret); > + qemuDomainObjExitMonitorWithDriver(driver, vm); > + if (ret < 0) > + goto cleanup; > + } > + } > + > +cleanup: > return ret; > } > > @@ -2721,7 +2766,7 @@ static int qemudStartVMDaemon(virConnectPtr conn, > if (qemudInitCpuAffinity(vm) < 0) > goto abort; > > - if (qemuInitPasswords(driver, vm) < 0) > + if (qemuInitPasswords(conn, driver, vm, qemuCmdFlags) < 0) > goto abort; > > /* If we have -device, then addresses are assigned explicitly. > diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c > index 64c6cba..c1d369b 100644 > --- a/src/qemu/qemu_monitor.c > +++ b/src/qemu/qemu_monitor.c > @@ -1331,3 +1331,18 @@ int qemuMonitorAddDrive(qemuMonitorPtr mon, > ret = qemuMonitorTextAddDrive(mon, drivestr); > return ret; > } > + > + > +int qemuMonitorSetDrivePassphrase(qemuMonitorPtr mon, > + const char *alias, > + const char *passphrase) > +{ > + DEBUG("mon=%p, fd=%d alias=%s passphrase=%p(value hidden)", mon, mon->fd, alias, passphrase); > + int ret; > + > + if (mon->json) > + ret = qemuMonitorJSONSetDrivePassphrase(mon, alias, passphrase); > + else > + ret = qemuMonitorTextSetDrivePassphrase(mon, alias, passphrase); > + return ret; > +} > diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h > index a330eff..786ad7a 100644 > --- a/src/qemu/qemu_monitor.h > +++ b/src/qemu/qemu_monitor.h > @@ -291,4 +291,8 @@ int qemuMonitorAddDevice(qemuMonitorPtr mon, > int qemuMonitorAddDrive(qemuMonitorPtr mon, > const char *drivestr); > > +int qemuMonitorSetDrivePassphrase(qemuMonitorPtr mon, > + const char *alias, > + const char *passphrase); > + > #endif /* QEMU_MONITOR_H */ > diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c > index 032afef..c9b8d60 100644 > --- a/src/qemu/qemu_monitor_json.c > +++ b/src/qemu/qemu_monitor_json.c > @@ -1841,3 +1841,36 @@ int qemuMonitorJSONAddDrive(qemuMonitorPtr mon, > virJSONValueFree(reply); > return ret; > } > + > + > +int qemuMonitorJSONSetDrivePassphrase(qemuMonitorPtr mon, > + const char *alias, > + const char *passphrase) > +{ > + int ret; > + virJSONValuePtr cmd; > + virJSONValuePtr reply = NULL; > + char *drive; > + > + if (virAsprintf(&drive, "%s%s", QEMU_DRIVE_HOST_PREFIX, alias) < 0) { > + virReportOOMError(); > + return -1; > + } > + > + cmd = qemuMonitorJSONMakeCommand("block_passwd", > + "s:device", drive, > + "s:password", passphrase, > + NULL); > + VIR_FREE(drive); > + if (!cmd) > + return -1; > + > + ret = qemuMonitorJSONCommand(mon, cmd, &reply); > + > + if (ret == 0) > + ret = qemuMonitorJSONCheckError(cmd, reply); > + > + virJSONValueFree(cmd); > + virJSONValueFree(reply); > + return ret; > +} > diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h > index ac6458c..65a70e3 100644 > --- a/src/qemu/qemu_monitor_json.h > +++ b/src/qemu/qemu_monitor_json.h > @@ -162,4 +162,8 @@ int qemuMonitorJSONAddDevice(qemuMonitorPtr mon, > int qemuMonitorJSONAddDrive(qemuMonitorPtr mon, > const char *drivestr); > > +int qemuMonitorJSONSetDrivePassphrase(qemuMonitorPtr mon, > + const char *alias, > + const char *passphrase); > + > #endif /* QEMU_MONITOR_JSON_H */ > diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c > index a6a4598..e993699 100644 > --- a/src/qemu/qemu_monitor_text.c > +++ b/src/qemu/qemu_monitor_text.c > @@ -2127,3 +2127,50 @@ cleanup: > VIR_FREE(safe_str); > return ret; > } > + > + > +int qemuMonitorTextSetDrivePassphrase(qemuMonitorPtr mon, > + const char *alias, > + const char *passphrase) > +{ > + char *cmd = NULL; > + char *reply = NULL; > + int ret = -1; > + char *safe_str; > + > + safe_str = qemuMonitorEscapeArg(passphrase); > + if (!safe_str) { > + virReportOOMError(); > + return -1; > + } > + > + ret = virAsprintf(&cmd, "block_passwd %s%s \"%s\"", QEMU_DRIVE_HOST_PREFIX, alias, safe_str); > + if (ret == -1) { > + virReportOOMError(); > + goto cleanup; > + } > + > + if (qemuMonitorCommand(mon, cmd, &reply) < 0) { > + qemuReportError(VIR_ERR_OPERATION_FAILED, > + _("failed to close fd in qemu with '%s'"), cmd); > + goto cleanup; > + } > + > + if (strstr(reply, "\nunknown command:")) { > + qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", > + _("setting disk password is not supported")); > + goto cleanup; > + } else if (strstr(reply, "The entered password is invalid")) { > + qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", > + _("the disk password is incorrect")); > + goto cleanup; > + } > + > + ret = 0; > + > +cleanup: > + VIR_FREE(cmd); > + VIR_FREE(reply); > + VIR_FREE(safe_str); > + return ret; > +} > diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h > index 12d75f5..1937e99 100644 > --- a/src/qemu/qemu_monitor_text.h > +++ b/src/qemu/qemu_monitor_text.h > @@ -166,4 +166,8 @@ int qemuMonitorTextAddDevice(qemuMonitorPtr mon, > int qemuMonitorTextAddDrive(qemuMonitorPtr mon, > const char *drivestr); > > +int qemuMonitorTextSetDrivePassphrase(qemuMonitorPtr mon, > + const char *alias, > + const char *passphrase); > + > #endif /* QEMU_MONITOR_TEXT_H */ Looks fine, ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list