qemu: Reuse qemuBlockStorageSourceAttachApply in disk hotplug

Create a new "Prepare" function and move the drive add code into the new
helpers. This will eventually allow to simplify and unify the attaching
code for use with blockdev at the same time as providing compatibility
with older qemus.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Peter Krempa 2018-05-16 13:39:22 +02:00
parent d5c5c841e0
commit ca174424ba
5 changed files with 63 additions and 22 deletions

View File

@ -24,9 +24,12 @@
#include "viralloc.h"
#include "virstring.h"
#include "virlog.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
VIR_LOG_INIT("qemu.qemu_block");
/* qemu declares the buffer for node names as a 32 byte array */
static const size_t qemuBlockNodeNameBufSize = 32;
@ -1482,6 +1485,8 @@ qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data)
virJSONValueFree(data->storageProps);
virJSONValueFree(data->formatProps);
VIR_FREE(data->driveCmd);
VIR_FREE(data->driveAlias);
VIR_FREE(data);
}
@ -1563,6 +1568,13 @@ qemuBlockStorageSourceAttachApply(qemuMonitorPtr mon,
data->formatAttached = true;
}
if (data->driveCmd) {
if (qemuMonitorAddDrive(mon, data->driveCmd) < 0)
return -1;
data->driveAdded = true;
}
return 0;
}
@ -1585,6 +1597,12 @@ qemuBlockStorageSourceAttachRollback(qemuMonitorPtr mon,
virErrorPreserveLast(&orig_err);
if (data->driveAdded) {
if (qemuMonitorDriveDel(mon, data->driveAlias) < 0)
VIR_WARN("Unable to remove drive %s (%s) after failed "
"qemuMonitorAddDevice", data->driveAlias, data->driveCmd);
}
if (data->formatAttached)
ignore_value(qemuMonitorBlockdevDel(mon, data->formatNodeName));

View File

@ -78,6 +78,10 @@ struct qemuBlockStorageSourceAttachData {
virJSONValuePtr formatProps;
const char *formatNodeName;
bool formatAttached;
char *driveCmd;
char *driveAlias;
bool driveAdded;
};

View File

@ -1644,7 +1644,7 @@ qemuBuildDiskFrontendAttributes(virDomainDiskDefPtr disk,
}
char *
static char *
qemuBuildDriveStr(virDomainDiskDefPtr disk,
bool bootable,
virQEMUCapsPtr qemuCaps)
@ -10458,3 +10458,30 @@ qemuBuildHotpluggableCPUProps(const virDomainVcpuDef *vcpu)
virJSONValueFree(ret);
return NULL;
}
/**
* qemuBuildStorageSourceAttachPrepareDrive:
* @disk: disk object to prepare
* @qemuCaps: qemu capabilities object
*
* Prepare qemuBlockStorageSourceAttachDataPtr for use with the old approach
* using -drive/drive_add. See qemuBlockStorageSourceAttachPrepareBlockdev.
*/
qemuBlockStorageSourceAttachDataPtr
qemuBuildStorageSourceAttachPrepareDrive(virDomainDiskDefPtr disk,
virQEMUCapsPtr qemuCaps)
{
qemuBlockStorageSourceAttachDataPtr data = NULL;
if (VIR_ALLOC(data) < 0)
return NULL;
if (!(data->driveCmd = qemuBuildDriveStr(disk, false, qemuCaps)) ||
!(data->driveAlias = qemuAliasDiskDriveFromDisk(disk))) {
qemuBlockStorageSourceAttachDataFree(data);
return NULL;
}
return data;
}

View File

@ -28,6 +28,7 @@
# include "domain_conf.h"
# include "vircommand.h"
# include "capabilities.h"
# include "qemu_block.h"
# include "qemu_conf.h"
# include "qemu_domain.h"
# include "qemu_domain_address.h"
@ -102,10 +103,9 @@ char *qemuBuildNicDevStr(virDomainDefPtr def,
char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk);
/* Both legacy & current support */
char *qemuBuildDriveStr(virDomainDiskDefPtr disk,
bool bootable,
virQEMUCapsPtr qemuCaps);
qemuBlockStorageSourceAttachDataPtr
qemuBuildStorageSourceAttachPrepareDrive(virDomainDiskDefPtr disk,
virQEMUCapsPtr qemuCaps);
/* Current, best practice */
char *qemuBuildDriveDevStr(const virDomainDef *def,

View File

@ -35,6 +35,7 @@
#include "qemu_interface.h"
#include "qemu_process.h"
#include "qemu_security.h"
#include "qemu_block.h"
#include "domain_audit.h"
#include "netdev_bandwidth_conf.h"
#include "domain_nwfilter.h"
@ -390,15 +391,13 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver,
{
int ret = -1;
qemuDomainObjPrivatePtr priv = vm->privateData;
qemuBlockStorageSourceAttachDataPtr data = NULL;
virErrorPtr orig_err;
char *devstr = NULL;
char *drivestr = NULL;
char *drivealias = NULL;
char *unmanagedPrmgrAlias = NULL;
char *managedPrmgrAlias = NULL;
char *encobjAlias = NULL;
char *secobjAlias = NULL;
bool driveAdded = false;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virJSONValuePtr secobjProps = NULL;
virJSONValuePtr encobjProps = NULL;
@ -439,16 +438,13 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver,
!(unmanagedPrmgrProps = qemuBuildPRManagerInfoProps(disk->src)))
goto error;
if (!(data = qemuBuildStorageSourceAttachPrepareDrive(disk, priv->qemuCaps)))
goto error;
if (disk->src->haveTLS == VIR_TRISTATE_BOOL_YES &&
qemuDomainAddDiskSrcTLSObject(driver, vm, disk->src) < 0)
goto error;
if (!(drivestr = qemuBuildDriveStr(disk, false, priv->qemuCaps)))
goto error;
if (!(drivealias = qemuAliasDiskDriveFromDisk(disk)))
goto error;
if (!(devstr = qemuBuildDriveDevStr(vm->def, disk, 0, priv->qemuCaps)))
goto error;
@ -473,9 +469,8 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver,
qemuMonitorAddObject(priv->mon, &unmanagedPrmgrProps, &unmanagedPrmgrAlias) < 0)
goto exit_monitor;
if (qemuMonitorAddDrive(priv->mon, drivestr) < 0)
if (qemuBlockStorageSourceAttachApply(priv->mon, data) < 0)
goto exit_monitor;
driveAdded = true;
if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
goto exit_monitor;
@ -491,6 +486,7 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver,
ret = 0;
cleanup:
qemuBlockStorageSourceAttachDataFree(data);
virJSONValueFree(managedPrmgrProps);
virJSONValueFree(unmanagedPrmgrProps);
virJSONValueFree(encobjProps);
@ -500,18 +496,14 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver,
VIR_FREE(unmanagedPrmgrAlias);
VIR_FREE(secobjAlias);
VIR_FREE(encobjAlias);
VIR_FREE(drivealias);
VIR_FREE(drivestr);
VIR_FREE(devstr);
virObjectUnref(cfg);
return ret;
exit_monitor:
qemuBlockStorageSourceAttachRollback(priv->mon, data);
virErrorPreserveLast(&orig_err);
if (driveAdded && qemuMonitorDriveDel(priv->mon, drivealias) < 0) {
VIR_WARN("Unable to remove drive %s (%s) after failed "
"qemuMonitorAddDevice", drivealias, drivestr);
}
if (secobjAlias)
ignore_value(qemuMonitorDelObject(priv->mon, secobjAlias));
if (encobjAlias)