mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
qemu: Implement virDomainGetDiskErrors
This commit is contained in:
parent
342fc56f58
commit
e17e3ed6aa
@ -175,6 +175,7 @@ struct qemuDomainDiskInfo {
|
|||||||
bool removable;
|
bool removable;
|
||||||
bool locked;
|
bool locked;
|
||||||
bool tray_open;
|
bool tray_open;
|
||||||
|
int io_status;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __QEMUD_CONF_H */
|
#endif /* __QEMUD_CONF_H */
|
||||||
|
@ -11728,6 +11728,91 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuDomainGetDiskErrors(virDomainPtr dom,
|
||||||
|
virDomainDiskErrorPtr errors,
|
||||||
|
unsigned int nerrors,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
struct qemud_driver *driver = dom->conn->privateData;
|
||||||
|
virDomainObjPtr vm = NULL;
|
||||||
|
qemuDomainObjPrivatePtr priv;
|
||||||
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||||
|
virHashTablePtr table = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
int i;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
virCheckFlags(0, -1);
|
||||||
|
|
||||||
|
qemuDriverLock(driver);
|
||||||
|
virUUIDFormat(dom->uuid, uuidstr);
|
||||||
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
||||||
|
qemuDriverUnlock(driver);
|
||||||
|
|
||||||
|
if (!vm) {
|
||||||
|
qemuReportError(VIR_ERR_NO_DOMAIN,
|
||||||
|
_("no domain with matching uuid '%s'"), uuidstr);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv = vm->privateData;
|
||||||
|
|
||||||
|
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!virDomainObjIsActive(vm)) {
|
||||||
|
qemuReportError(VIR_ERR_OPERATION_INVALID,
|
||||||
|
"%s", _("domain is not running"));
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!errors) {
|
||||||
|
ret = vm->def->ndisks;
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
|
table = qemuMonitorGetBlockInfo(priv->mon);
|
||||||
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
|
if (!table)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
|
for (i = n = 0; i < vm->def->ndisks; i++) {
|
||||||
|
struct qemuDomainDiskInfo *info;
|
||||||
|
virDomainDiskDefPtr disk = vm->def->disks[i];
|
||||||
|
|
||||||
|
if ((info = virHashLookup(table, disk->info.alias)) &&
|
||||||
|
info->io_status != VIR_DOMAIN_DISK_ERROR_NONE) {
|
||||||
|
if (n == nerrors)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!(errors[n].disk = strdup(disk->dst))) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
errors[n].error = info->io_status;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = n;
|
||||||
|
|
||||||
|
endjob:
|
||||||
|
if (qemuDomainObjEndJob(driver, vm) == 0)
|
||||||
|
vm = NULL;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (vm)
|
||||||
|
virDomainObjUnlock(vm);
|
||||||
|
virHashFree(table);
|
||||||
|
if (ret < 0) {
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
VIR_FREE(errors[i].disk);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static virDriver qemuDriver = {
|
static virDriver qemuDriver = {
|
||||||
.no = VIR_DRV_QEMU,
|
.no = VIR_DRV_QEMU,
|
||||||
.name = "QEMU",
|
.name = "QEMU",
|
||||||
@ -11881,6 +11966,7 @@ static virDriver qemuDriver = {
|
|||||||
.domainGetNumaParameters = qemuDomainGetNumaParameters, /* 0.9.9 */
|
.domainGetNumaParameters = qemuDomainGetNumaParameters, /* 0.9.9 */
|
||||||
.domainGetInterfaceParameters = qemuDomainGetInterfaceParameters, /* 0.9.9 */
|
.domainGetInterfaceParameters = qemuDomainGetInterfaceParameters, /* 0.9.9 */
|
||||||
.domainSetInterfaceParameters = qemuDomainSetInterfaceParameters, /* 0.9.9 */
|
.domainSetInterfaceParameters = qemuDomainSetInterfaceParameters, /* 0.9.9 */
|
||||||
|
.domainGetDiskErrors = qemuDomainGetDiskErrors, /* 0.9.10 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,6 +87,20 @@ VIR_ENUM_IMPL(qemuMonitorVMStatus,
|
|||||||
"postmigrate", "prelaunch", "finish-migrate", "restore-vm",
|
"postmigrate", "prelaunch", "finish-migrate", "restore-vm",
|
||||||
"running", "save-vm", "shutdown", "watchdog")
|
"running", "save-vm", "shutdown", "watchdog")
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
QEMU_MONITOR_BLOCK_IO_STATUS_OK,
|
||||||
|
QEMU_MONITOR_BLOCK_IO_STATUS_FAILED,
|
||||||
|
QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE,
|
||||||
|
|
||||||
|
QEMU_MONITOR_BLOCK_IO_STATUS_LAST
|
||||||
|
} qemuMonitorBlockIOStatus;
|
||||||
|
|
||||||
|
VIR_ENUM_DECL(qemuMonitorBlockIOStatus)
|
||||||
|
|
||||||
|
VIR_ENUM_IMPL(qemuMonitorBlockIOStatus,
|
||||||
|
QEMU_MONITOR_BLOCK_IO_STATUS_LAST,
|
||||||
|
"ok", "failed", "nospace")
|
||||||
|
|
||||||
char *qemuMonitorEscapeArg(const char *in)
|
char *qemuMonitorEscapeArg(const char *in)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@ -1227,6 +1241,32 @@ int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
qemuMonitorBlockIOStatusToError(const char *status)
|
||||||
|
{
|
||||||
|
int st = qemuMonitorBlockIOStatusTypeFromString(status);
|
||||||
|
|
||||||
|
if (st < 0) {
|
||||||
|
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("unknown block IO status: %s"), status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ((qemuMonitorBlockIOStatus) st) {
|
||||||
|
case QEMU_MONITOR_BLOCK_IO_STATUS_OK:
|
||||||
|
return VIR_DOMAIN_DISK_ERROR_NONE;
|
||||||
|
case QEMU_MONITOR_BLOCK_IO_STATUS_FAILED:
|
||||||
|
return VIR_DOMAIN_DISK_ERROR_UNSPEC;
|
||||||
|
case QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE:
|
||||||
|
return VIR_DOMAIN_DISK_ERROR_NO_SPACE;
|
||||||
|
|
||||||
|
/* unreachable */
|
||||||
|
case QEMU_MONITOR_BLOCK_IO_STATUS_LAST:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
virHashTablePtr
|
virHashTablePtr
|
||||||
qemuMonitorGetBlockInfo(qemuMonitorPtr mon)
|
qemuMonitorGetBlockInfo(qemuMonitorPtr mon)
|
||||||
{
|
{
|
||||||
|
@ -236,6 +236,7 @@ int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
|
|||||||
virDomainMemoryStatPtr stats,
|
virDomainMemoryStatPtr stats,
|
||||||
unsigned int nr_stats);
|
unsigned int nr_stats);
|
||||||
|
|
||||||
|
int qemuMonitorBlockIOStatusToError(const char *status);
|
||||||
virHashTablePtr qemuMonitorGetBlockInfo(qemuMonitorPtr mon);
|
virHashTablePtr qemuMonitorGetBlockInfo(qemuMonitorPtr mon);
|
||||||
struct qemuDomainDiskInfo *
|
struct qemuDomainDiskInfo *
|
||||||
qemuMonitorBlockInfoLookup(virHashTablePtr blockInfo,
|
qemuMonitorBlockInfoLookup(virHashTablePtr blockInfo,
|
||||||
|
@ -1389,6 +1389,7 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
|||||||
virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
|
virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
|
||||||
struct qemuDomainDiskInfo *info;
|
struct qemuDomainDiskInfo *info;
|
||||||
const char *thisdev;
|
const char *thisdev;
|
||||||
|
const char *status;
|
||||||
|
|
||||||
if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
|
if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
|
||||||
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
@ -1434,6 +1435,13 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
|
|||||||
*/
|
*/
|
||||||
ignore_value(virJSONValueObjectGetBoolean(dev, "tray-open",
|
ignore_value(virJSONValueObjectGetBoolean(dev, "tray-open",
|
||||||
&info->tray_open));
|
&info->tray_open));
|
||||||
|
|
||||||
|
/* Missing io-status indicates no error */
|
||||||
|
if ((status = virJSONValueObjectGetString(dev, "io-status"))) {
|
||||||
|
info->io_status = qemuMonitorBlockIOStatusToError(status);
|
||||||
|
if (info->io_status < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -839,6 +839,21 @@ int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
|
|||||||
VIR_DEBUG("error reading tray_open: %s", p);
|
VIR_DEBUG("error reading tray_open: %s", p);
|
||||||
else
|
else
|
||||||
info->tray_open = (tmp != 0);
|
info->tray_open = (tmp != 0);
|
||||||
|
} else if (STRPREFIX(p, "io-status=")) {
|
||||||
|
char *end;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
p += strlen("io-status=");
|
||||||
|
end = strchr(p, ' ');
|
||||||
|
if (!end || end > eol)
|
||||||
|
end = eol;
|
||||||
|
|
||||||
|
c = *end;
|
||||||
|
*end = '\0';
|
||||||
|
info->io_status = qemuMonitorBlockIOStatusToError(p);
|
||||||
|
*end = c;
|
||||||
|
if (info->io_status < 0)
|
||||||
|
goto cleanup;
|
||||||
} else {
|
} else {
|
||||||
/* ignore because we don't parse all options */
|
/* ignore because we don't parse all options */
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user