From patchwork Mon Jan 9 11:24:16 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Capitulino X-Patchwork-Id: 134998 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id A313DB6F71 for ; Mon, 9 Jan 2012 22:25:50 +1100 (EST) Received: from localhost ([::1]:39281 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RkDM9-00030g-6u for incoming@patchwork.ozlabs.org; Mon, 09 Jan 2012 06:25:37 -0500 Received: from eggs.gnu.org ([140.186.70.92]:52675) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RkDLQ-0001AG-BP for qemu-devel@nongnu.org; Mon, 09 Jan 2012 06:24:56 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RkDLF-0006hh-RI for qemu-devel@nongnu.org; Mon, 09 Jan 2012 06:24:47 -0500 Received: from mx1.redhat.com ([209.132.183.28]:11161) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RkDLF-0006hc-Gy for qemu-devel@nongnu.org; Mon, 09 Jan 2012 06:24:41 -0500 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q09BOdcP009335 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 9 Jan 2012 06:24:39 -0500 Received: from localhost (ovpn-113-68.phx2.redhat.com [10.3.113.68]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q09BOcaX009633; Mon, 9 Jan 2012 06:24:38 -0500 From: Luiz Capitulino To: qemu-devel@nongnu.org Date: Mon, 9 Jan 2012 09:24:16 -0200 Message-Id: <1326108257-13042-10-git-send-email-lcapitulino@redhat.com> In-Reply-To: <1326108257-13042-1-git-send-email-lcapitulino@redhat.com> References: <1326108257-13042-1-git-send-email-lcapitulino@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 209.132.183.28 Cc: kwolf@redhat.com, aliguori@us.ibm.com, mdroth@linux.vnet.ibm.com Subject: [Qemu-devel] [PATCH 09/10] qapi: Convert change X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Anthony Liguori Signed-off-by: Luiz Capitulino --- blockdev.c | 54 +++++++++++++++++++++++++++----------- blockdev.h | 5 ++- hmp-commands.hx | 3 +- hmp.c | 57 +++++++++++++++++++++++++++++++++++++++++ hmp.h | 1 + monitor.c | 74 ------------------------------------------------------ qapi-schema.json | 36 ++++++++++++++++++++++++++ qmp-commands.hx | 5 +--- qmp.c | 44 ++++++++++++++++++++++++++++++++ 9 files changed, 181 insertions(+), 98 deletions(-) diff --git a/blockdev.c b/blockdev.c index 124fbe6..8df78ce 100644 --- a/blockdev.c +++ b/blockdev.c @@ -717,8 +717,31 @@ void qmp_block_passwd(const char *device, const char *password, Error **errp) } } -int do_change_block(Monitor *mon, const char *device, - const char *filename, const char *fmt) +static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename, + int bdrv_flags, BlockDriver *drv, + const char *password, Error **errp) +{ + if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) { + error_set(errp, QERR_OPEN_FILE_FAILED, filename); + return; + } + + if (bdrv_key_required(bs)) { + if (password) { + if (bdrv_set_key(bs, password) < 0) { + error_set(errp, QERR_INVALID_PASSWORD); + } + } else { + error_set(errp, QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs), + bdrv_get_encrypted_filename(bs)); + } + } else if (password) { + error_set(errp, QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs)); + } +} + +void qmp_change_blockdev(const char *device, const char *filename, + bool has_format, const char *format, Error **errp) { BlockDriverState *bs; BlockDriver *drv = NULL; @@ -727,29 +750,28 @@ int do_change_block(Monitor *mon, const char *device, bs = bdrv_find(device); if (!bs) { - qerror_report(QERR_DEVICE_NOT_FOUND, device); - return -1; + error_set(errp, QERR_DEVICE_NOT_FOUND, device); + return; } - if (fmt) { - drv = bdrv_find_whitelisted_format(fmt); + + if (format) { + drv = bdrv_find_whitelisted_format(format); if (!drv) { - qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt); - return -1; + error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); + return; } } + eject_device(bs, 0, &err); if (error_is_set(&err)) { - qerror_report_err(err); - error_free(err); - return -1; + error_propagate(errp, err); + return; } + bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR; bdrv_flags |= bdrv_is_snapshot(bs) ? BDRV_O_SNAPSHOT : 0; - if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) { - qerror_report(QERR_OPEN_FILE_FAILED, filename); - return -1; - } - return monitor_read_bdrv_key_start(mon, bs, NULL, NULL); + + qmp_bdrv_open_encrypted(bs, filename, bdrv_flags, drv, NULL, errp); } /* throttling disk I/O limits */ diff --git a/blockdev.h b/blockdev.h index 1937b28..b077449 100644 --- a/blockdev.h +++ b/blockdev.h @@ -11,6 +11,7 @@ #define BLOCKDEV_H #include "block.h" +#include "error.h" #include "qemu-queue.h" void blockdev_mark_auto_del(BlockDriverState *bs); @@ -57,9 +58,9 @@ DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi); DriveInfo *add_init_drive(const char *opts); +void qmp_change_blockdev(const char *device, const char *filename, + bool has_format, const char *format, Error **errp); void do_commit(Monitor *mon, const QDict *qdict); -int do_change_block(Monitor *mon, const char *device, - const char *filename, const char *fmt); int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data); int do_block_set_io_throttle(Monitor *mon, const QDict *qdict, QObject **ret_data); diff --git a/hmp-commands.hx b/hmp-commands.hx index f02b645..9f44690 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -107,8 +107,7 @@ ETEXI .args_type = "device:B,target:F,arg:s?", .params = "device filename [format]", .help = "change a removable medium, optional format", - .user_print = monitor_user_noop, - .mhandler.cmd_new = do_change, + .mhandler.cmd = hmp_change, }, STEXI diff --git a/hmp.c b/hmp.c index 404c8d6..89fa8e7 100644 --- a/hmp.c +++ b/hmp.c @@ -710,3 +710,60 @@ void hmp_eject(Monitor *mon, const QDict *qdict) qmp_eject(device, true, force, &err); hmp_handle_error(mon, &err); } + +static void hmp_change_read_arg(Monitor *mon, const char *password, + void *opaque) +{ + qmp_change_vnc_password(password, NULL); + monitor_read_command(mon, 1); +} + +static void cb_hmp_change_bdrv_pwd(Monitor *mon, const char *password, + void *opaque) +{ + Error *encryption_err = opaque; + Error *err = NULL; + const char *device; + + device = error_get_field(encryption_err, "device"); + + qmp_block_passwd(device, password, &err); + hmp_handle_error(mon, &err); + error_free(encryption_err); + + monitor_read_command(mon, 1); +} + +void hmp_change(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *target = qdict_get_str(qdict, "target"); + const char *arg = qdict_get_try_str(qdict, "arg"); + Error *err = NULL; + + if (strcmp(device, "vnc") == 0 && + (strcmp(target, "passwd") == 0 || + strcmp(target, "password") == 0)) { + if (!arg) { + monitor_read_password(mon, hmp_change_read_arg, NULL); + return; + } + } + + qmp_change(device, target, !!arg, arg, &err); + if (error_is_type(err, QERR_DEVICE_ENCRYPTED)) { + monitor_printf(mon, "%s (%s) is encrypted.\n", + error_get_field(err, "device"), + error_get_field(err, "filename")); + if (!monitor_get_rs(mon)) { + monitor_printf(mon, + "terminal does not support password prompting\n"); + error_free(err); + return; + } + readline_start(monitor_get_rs(mon), "Password: ", 1, + cb_hmp_change_bdrv_pwd, err); + return; + } + hmp_handle_error(mon, &err); +} diff --git a/hmp.h b/hmp.h index 29dbf93..621bdc2 100644 --- a/hmp.h +++ b/hmp.h @@ -52,5 +52,6 @@ void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict); void hmp_set_password(Monitor *mon, const QDict *qdict); void hmp_expire_password(Monitor *mon, const QDict *qdict); void hmp_eject(Monitor *mon, const QDict *qdict); +void hmp_change(Monitor *mon, const QDict *qdict); #endif diff --git a/monitor.c b/monitor.c index f85a9d2..187083c 100644 --- a/monitor.c +++ b/monitor.c @@ -810,80 +810,6 @@ static void do_trace_print_events(Monitor *mon) trace_print_events((FILE *)mon, &monitor_fprintf); } -#ifdef CONFIG_VNC -static int change_vnc_password(const char *password) -{ - if (!password || !password[0]) { - if (vnc_display_disable_login(NULL)) { - qerror_report(QERR_SET_PASSWD_FAILED); - return -1; - } - return 0; - } - - if (vnc_display_password(NULL, password) < 0) { - qerror_report(QERR_SET_PASSWD_FAILED); - return -1; - } - - return 0; -} - -static void change_vnc_password_cb(Monitor *mon, const char *password, - void *opaque) -{ - change_vnc_password(password); - monitor_read_command(mon, 1); -} - -static int do_change_vnc(Monitor *mon, const char *target, const char *arg) -{ - if (strcmp(target, "passwd") == 0 || - strcmp(target, "password") == 0) { - if (arg) { - char password[9]; - strncpy(password, arg, sizeof(password)); - password[sizeof(password) - 1] = '\0'; - return change_vnc_password(password); - } else { - return monitor_read_password(mon, change_vnc_password_cb, NULL); - } - } else { - if (vnc_display_open(NULL, target) < 0) { - qerror_report(QERR_VNC_SERVER_FAILED, target); - return -1; - } - } - - return 0; -} -#else -static int do_change_vnc(Monitor *mon, const char *target, const char *arg) -{ - qerror_report(QERR_FEATURE_DISABLED, "vnc"); - return -ENODEV; -} -#endif - -/** - * do_change(): Change a removable medium, or VNC configuration - */ -static int do_change(Monitor *mon, const QDict *qdict, QObject **ret_data) -{ - const char *device = qdict_get_str(qdict, "device"); - const char *target = qdict_get_str(qdict, "target"); - const char *arg = qdict_get_try_str(qdict, "arg"); - int ret; - - if (strcmp(device, "vnc") == 0) { - ret = do_change_vnc(mon, target, arg); - } else { - ret = do_change_block(mon, device, target, arg); - } - - return ret; -} - static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_data) { const char *protocol = qdict_get_str(qdict, "protocol"); diff --git a/qapi-schema.json b/qapi-schema.json index 171e781..36fd156 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1367,3 +1367,39 @@ # executing this command. ## { 'command': 'change-vnc-password', 'data': {'password': 'str'} } + +## +# @change: +# +# This command is multiple commands multiplexed together. +# +# @device: This is normally the name of a block device but it may also be 'vnc'. +# when it's 'vnc', then sub command depends on @target +# +# @target: If @device is a block device, then this is the new filename. +# If @device is 'vnc', then if the value 'password' selects the vnc +# change password command. Otherwise, this specifies a new server URI +# address to listen to for VNC connections. +# +# @arg: If @device is a block device, then this is an optional format to open +# the device with. +# If @device is 'vnc' and @target is 'password', this is the new VNC +# password to set. If this argument is an empty string, then no future +# logins will be allowed. +# +# Returns: Nothing on success. +# If @device is not a valid block device, DeviceNotFound +# If @format is not a valid block format, InvalidBlockFormat +# If the new block device is encrypted, DeviceEncrypted. Note that +# if this error is returned, the device has been opened successfully +# and an additional call to @block_passwd is required to set the +# device's password. The behavior of reads and writes to the block +# device between when these calls are executed is undefined. +# +# Notes: It is strongly recommended that this interface is not used especially +# for changing block devices. +# +# Since: 0.14.0 +## +{ 'command': 'change', + 'data': {'device': 'str', 'target': 'str', '*arg': 'str'} } diff --git a/qmp-commands.hx b/qmp-commands.hx index 886d589..bfae81f 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -110,10 +110,7 @@ EQMP { .name = "change", .args_type = "device:B,target:F,arg:s?", - .params = "device filename [format]", - .help = "change a removable medium, optional format", - .user_print = monitor_user_noop, - .mhandler.cmd_new = do_change, + .mhandler.cmd_new = qmp_marshal_input_change, }, SQMP diff --git a/qmp.c b/qmp.c index 00ae7ec..3bd8c75 100644 --- a/qmp.c +++ b/qmp.c @@ -21,6 +21,7 @@ #include "hw/qdev.h" #include "qapi/qmp-input-visitor.h" #include "qapi/qmp-output-visitor.h" +#include "blockdev.h" NameInfo *qmp_query_name(Error **errp) { @@ -343,6 +344,7 @@ void qmp_expire_password(const char *protocol, const char *whenstr, error_set(errp, QERR_INVALID_PARAMETER, "protocol"); } +#ifdef CONFIG_VNC void qmp_change_vnc_password(const char *password, Error **errp) { if (!password || !password[0]) { @@ -356,3 +358,45 @@ void qmp_change_vnc_password(const char *password, Error **errp) error_set(errp, QERR_SET_PASSWD_FAILED); } } + +static void qmp_change_vnc_listen(const char *target, Error **err) +{ + if (vnc_display_open(NULL, target) < 0) { + error_set(err, QERR_VNC_SERVER_FAILED, target); + } +} + +static void qmp_change_vnc(const char *target, bool has_arg, const char *arg, + Error **errp) +{ + if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) { + if (!has_arg) { + error_set(errp, QERR_MISSING_PARAMETER, "password"); + } else { + qmp_change_vnc_password(arg, errp); + } + } else { + qmp_change_vnc_listen(target, errp); + } +} +#else +void qmp_change_vnc_password(const char *password, Error **errp) +{ + error_set(errp, QERR_FEATURE_DISABLED, "vnc"); +} +static void qmp_change_vnc(const char *target, bool has_arg, const char *arg, + Error **errp) +{ + error_set(errp, QERR_FEATURE_DISABLED, "vnc"); +} +#endif /* !CONFIG_VNC */ + +void qmp_change(const char *device, const char *target, + bool has_arg, const char *arg, Error **err) +{ + if (strcmp(device, "vnc") == 0) { + qmp_change_vnc(target, has_arg, arg, err); + } else { + qmp_change_blockdev(device, target, has_arg, arg, err); + } +}