monitor: allow device_del to accept QOM paths

Currently device_del requires that the client provide the
device short ID. device_add allows devices to be created
without giving an ID, at which point there is no way to
delete them with device_del. The QOM object path, however,
provides an alternative way to identify the devices.

Allowing device_del to accept an object path ensures all
devices are deletable regardless of whether they have an
ID.

 (qemu) device_add usb-mouse
 (qemu) qom-list /machine/peripheral-anon
 device[0] (child<usb-mouse>)
 type (string)
 (qemu) device_del /machine/peripheral-anon/device[0]

Devices are required to be marked as hotpluggable
otherwise an error is raised

 (qemu) device_del /machine/unattached/device[4]
 Device 'PIIX3' does not support hotplugging

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-Id: <1441974836-17476-1-git-send-email-berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[Commit message touched up, accidental white-space change dropped]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
master
Daniel P. Berrange 2015-09-11 13:33:56 +01:00 committed by Markus Armbruster
parent 9e72681d16
commit 6287d827d4
4 changed files with 24 additions and 8 deletions

View File

@ -676,7 +676,8 @@ ETEXI
STEXI
@item device_del @var{id}
@findex device_del
Remove device @var{id}.
Remove device @var{id}. @var{id} may be a short ID
or a QOM object path.
ETEXI
{

View File

@ -1951,7 +1951,7 @@
#
# Remove a device from a guest
#
# @id: the name of the device
# @id: the name or QOM path of the device
#
# Returns: Nothing on success
# If @id is not a valid device, DeviceNotFound

View File

@ -771,12 +771,17 @@ void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp)
void qmp_device_del(const char *id, Error **errp)
{
Object *obj;
char *root_path = object_get_canonical_path(qdev_get_peripheral());
char *path = g_strdup_printf("%s/%s", root_path, id);
g_free(root_path);
obj = object_resolve_path_type(path, TYPE_DEVICE, NULL);
g_free(path);
if (id[0] == '/') {
obj = object_resolve_path(id, NULL);
} else {
char *root_path = object_get_canonical_path(qdev_get_peripheral());
char *path = g_strdup_printf("%s/%s", root_path, id);
g_free(root_path);
obj = object_resolve_path_type(path, TYPE_DEVICE, NULL);
g_free(path);
}
if (!obj) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
@ -784,6 +789,11 @@ void qmp_device_del(const char *id, Error **errp)
return;
}
if (!object_dynamic_cast(obj, TYPE_DEVICE)) {
error_setg(errp, "%s is not a hotpluggable device", id);
return;
}
qdev_unplug(DEVICE(obj), errp);
}

View File

@ -321,13 +321,18 @@ Remove a device.
Arguments:
- "id": the device's ID (json-string)
- "id": the device's ID or QOM path (json-string)
Example:
-> { "execute": "device_del", "arguments": { "id": "net1" } }
<- { "return": {} }
Example:
-> { "execute": "device_del", "arguments": { "id": "/machine/peripheral-anon/device[0]" } }
<- { "return": {} }
EQMP
{