mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 11:22:23 +00:00
qemu: block: Add helpers for hot-adding virStorageSource via blockdev
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@redhat.com> Reviewed-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
parent
d30fd1fc54
commit
ceb151b24b
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user