These helpers add infrastructure which simplifies adding and rolling back virStorageSources to a running qemu instance. Using of the helper structure and separate functions allows for a much cleaner code in the section dealing with the monitor. Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx> --- src/qemu/qemu_block.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_block.h | 34 +++++++++++ 2 files changed, 189 insertions(+) diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index a514e8a055..09437cdb40 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -1467,3 +1467,158 @@ qemuBlockStorageSourceGetBlockdevProps(virStorageSourcePtr src) virJSONValueFree(props); return ret; } + + +void +qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data) +{ + if (!data) + return; + + virJSONValueFree(data->storageProps); + virJSONValueFree(data->formatProps); + VIR_FREE(data); +} + + +/** + * qemuBlockStorageSourceAttachPrepareBlockdev: + * @src: storage source to prepare data from + * + * Creates a qemuBlockStorageSourceAttachData structure containing data to attach + * @src to a VM using the blockdev-add approach. Note that this function only + * creates the data for the storage source itself, any other related + * authentication/encryption/... objects need to be prepared separately. + * + * The changes are then applied using qemuBlockStorageSourceAttachApply. + * + * Returns the filled data structure on success or NULL on error and a libvirt + * error is reported + */ +qemuBlockStorageSourceAttachDataPtr +qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src) +{ + qemuBlockStorageSourceAttachDataPtr data; + qemuBlockStorageSourceAttachDataPtr ret = NULL; + + if (VIR_ALLOC(data) < 0) + return NULL; + + if (!(data->formatProps = qemuBlockStorageSourceGetBlockdevProps(src)) || + !(data->storageProps = qemuBlockStorageSourceGetBackendProps(src, false))) + goto cleanup; + + data->storageNodeName = src->nodestorage; + data->formatNodeName = src->nodeformat; + + VIR_STEAL_PTR(ret, data); + + cleanup: + qemuBlockStorageSourceAttachDataFree(data); + return ret; +} + + +/** + * qemuBlockStorageSourceAttachApply: + * @mon: monitor object + * @data: structure holding data of block device to apply + * + * Attaches a virStorageSource definition converted to + * qemuBlockStorageSourceAttachData to a running VM. This function expects being + * called after the monitor was entered. + * + * Returns 0 on success and -1 on error with a libvirt error reported. If an + * error occured, changes which were already applied need to be rolled back by + * calling qemuBlockStorageSourceAttachRollback. + */ +int +qemuBlockStorageSourceAttachApply(qemuMonitorPtr mon, + qemuBlockStorageSourceAttachDataPtr data) +{ + int rv; + + if (data->storageProps) { + rv = qemuMonitorBlockdevAdd(mon, data->storageProps); + data->storageProps = NULL; + + if (rv < 0) + return -1; + + data->storageAttached = true; + } + + if (data->formatProps) { + rv = qemuMonitorBlockdevAdd(mon, data->formatProps); + data->formatProps = NULL; + + if (rv < 0) + return -1; + + data->formatAttached = true; + } + + return 0; +} + + +/** + * qemuBlockStorageSourceAttachRollback: + * @mon: monitor object + * @data: structure holding data of block device to roll back + * + * Attempts a best effort rollback of changes which were made to a running VM by + * qemuBlockStorageSourceAttachApply. Preserves any existing errors. + * + * This function expects being called after the monitor was entered. + */ +void +qemuBlockStorageSourceAttachRollback(qemuMonitorPtr mon, + qemuBlockStorageSourceAttachDataPtr data) +{ + virErrorPtr orig_err; + + virErrorPreserveLast(&orig_err); + + if (data->formatAttached) + ignore_value(qemuMonitorBlockdevDel(mon, data->formatNodeName)); + + if (data->storageAttached) + ignore_value(qemuMonitorBlockdevDel(mon, data->storageNodeName)); + + virErrorRestore(&orig_err); +} + + +/** + * qemuBlockStorageSourceDetachOneBlockdev: + * @driver: qemu driver object + * @vm: domain object + * @asyncJob: currently running async job + * @src: storage source to detach + * + * Detaches one virStorageSource using blockdev-del. Note that this does not + * detach any authentication/encryption objects. This function enters the + * monitor internally. + */ +int +qemuBlockStorageSourceDetachOneBlockdev(virQEMUDriverPtr driver, + virDomainObjPtr vm, + qemuDomainAsyncJob asyncJob, + virStorageSourcePtr src) +{ + int ret; + + if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) + return -1; + + ret = qemuMonitorBlockdevDel(qemuDomainGetMonitor(vm), src->nodeformat); + + if (ret == 0) + ret = qemuMonitorBlockdevDel(qemuDomainGetMonitor(vm), src->nodestorage); + + if (qemuDomainObjExitMonitor(driver, vm) < 0) + return -1; + + return ret; +} diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h index f819c6f907..bbaf9ec0f1 100644 --- a/src/qemu/qemu_block.h +++ b/src/qemu/qemu_block.h @@ -67,4 +67,38 @@ qemuBlockStorageSourceGetURI(virStorageSourcePtr src); virJSONValuePtr qemuBlockStorageSourceGetBlockdevProps(virStorageSourcePtr src); + +typedef struct qemuBlockStorageSourceAttachData qemuBlockStorageSourceAttachData; +typedef qemuBlockStorageSourceAttachData *qemuBlockStorageSourceAttachDataPtr; +struct qemuBlockStorageSourceAttachData { + virJSONValuePtr storageProps; + const char *storageNodeName; + bool storageAttached; + + virJSONValuePtr formatProps; + const char *formatNodeName; + bool formatAttached; +}; + + +void +qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data); + +qemuBlockStorageSourceAttachDataPtr +qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src); + +int +qemuBlockStorageSourceAttachApply(qemuMonitorPtr mon, + qemuBlockStorageSourceAttachDataPtr data); + +void +qemuBlockStorageSourceAttachRollback(qemuMonitorPtr mon, + qemuBlockStorageSourceAttachDataPtr data); + +int +qemuBlockStorageSourceDetachOneBlockdev(virQEMUDriverPtr driver, + virDomainObjPtr vm, + qemuDomainAsyncJob asyncJob, + virStorageSourcePtr src); + #endif /* __QEMU_BLOCK_H__ */ -- 2.16.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list