[libvirt] [PATCH] qemu: Check for ejected media during startup and migration
by Michal Privoznik
If the daemon is restarted so we reconnect to monitor, cdrom media
can be ejected. In that case we don't want to show it in domain xml,
or require it on migration destination.
To check for disk status use 'info block' monitor command.
---
NB, the 'info block' is currently not updated yet. The qemu patches
that extend the monitor command are in a queue (that will be merged
quickly):
http://repo.or.cz/w/qemu/kevin.git
head for-anthony
The commit that introduce requested feature:
http://repo.or.cz/w/qemu/kevin.git/commitdiff/e4def80b36231e161b91fa984cd...
src/qemu/qemu_conf.h | 6 +++
src/qemu/qemu_driver.c | 7 +++
src/qemu/qemu_hotplug.c | 31 ++++++++++++++
src/qemu/qemu_hotplug.h | 2 +
src/qemu/qemu_monitor.c | 19 +++++++++
src/qemu/qemu_monitor.h | 4 ++
src/qemu/qemu_monitor_json.c | 89 +++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 3 +
src/qemu/qemu_monitor_text.c | 90 ++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_text.h | 3 +
src/qemu/qemu_process.c | 3 +
11 files changed, 257 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index e8b92a4..ff5cf23 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -165,4 +165,10 @@ void qemuDriverUnlock(struct qemud_driver *driver);
int qemudLoadDriverConfig(struct qemud_driver *driver,
const char *filename);
+struct qemuDomainDiskInfo {
+ bool removable;
+ bool locked;
+ bool tray_open;
+};
+
#endif /* __QEMUD_CONF_H */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b94d1c4..b10a56f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -8236,6 +8236,13 @@ qemuDomainMigrateBegin3(virDomainPtr domain,
goto endjob;
}
+ /* Check if there is and ejected media.
+ * We don't want to require them on the destination.
+ */
+
+ if (qemuDomainCheckEjectableMedia(driver, vm) < 0)
+ goto endjob;
+
if (!(xml = qemuMigrationBegin(driver, vm, xmlin,
cookieout, cookieoutlen)))
goto endjob;
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 6cfe392..91ac78a 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -150,6 +150,37 @@ error:
return -1;
}
+int
+qemuDomainCheckEjectableMedia(struct qemud_driver *driver,
+ virDomainObjPtr vm)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ int ret = -1;
+ int i;
+
+ for (i = 0; i < vm->def->ndisks; i++) {
+ virDomainDiskDefPtr disk = vm->def->disks[i];
+ struct qemuDomainDiskInfo info;
+
+ memset(&info, 0, sizeof(info));
+
+ qemuDomainObjEnterMonitor(driver, vm);
+ if (qemuMonitorGetBlockInfo(priv->mon, disk->info.alias, &info) < 0) {
+ qemuDomainObjExitMonitor(driver, vm);
+ goto cleanup;
+ }
+ qemuDomainObjExitMonitor(driver, vm);
+
+ if (info.tray_open && disk->src)
+ VIR_FREE(disk->src);
+ }
+
+ ret = 0;
+
+cleanup:
+ return ret;
+}
+
int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver,
virDomainObjPtr vm,
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index 65d1d30..aaaed88 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -31,6 +31,8 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainDiskDefPtr disk,
bool force);
+int qemuDomainCheckEjectableMedia(struct qemud_driver *driver,
+ virDomainObjPtr vm);
int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainDiskDefPtr disk);
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index fca8fa4..7005564 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1215,6 +1215,25 @@ int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
return ret;
}
+int qemuMonitorGetBlockInfo(qemuMonitorPtr mon,
+ const char *devname,
+ struct qemuDomainDiskInfo *info)
+{
+ int ret;
+
+ VIR_DEBUG("mon=%p dev=%p info=%p", mon, devname, info);
+ if (!mon) {
+ qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("monitor must not be NULL"));
+ return -1;
+ }
+
+ if (mon->json)
+ ret = qemuMonitorJSONGetBlockInfo(mon, devname, info);
+ else
+ ret = qemuMonitorTextGetBlockInfo(mon, devname, info);
+ return ret;
+}
int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
const char *devname,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 390eeff..a05d548 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -28,6 +28,7 @@
# include "internal.h"
# include "domain_conf.h"
+# include "qemu_conf.h"
# include "hash.h"
typedef struct _qemuMonitor qemuMonitor;
@@ -212,6 +213,9 @@ int qemuMonitorGetBalloonInfo(qemuMonitorPtr mon,
int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
virDomainMemoryStatPtr stats,
unsigned int nr_stats);
+int qemuMonitorGetBlockInfo(qemuMonitorPtr mon,
+ const char *devname,
+ struct qemuDomainDiskInfo *info);
int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
const char *devname,
long long *rd_req,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 3a81ec8..812a78e 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -1337,6 +1337,95 @@ cleanup:
}
+int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
+ const char *devname,
+ struct qemuDomainDiskInfo *info)
+{
+ int ret = 0;
+ bool found = false;
+ int i;
+
+ virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-block",
+ NULL);
+ virJSONValuePtr reply = NULL;
+ virJSONValuePtr devices;
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+ if (ret == 0)
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+ if (ret < 0)
+ goto cleanup;
+
+ ret = -1;
+
+ devices = virJSONValueObjectGet(reply, "return");
+ if (!devices || devices->type != VIR_JSON_TYPE_ARRAY) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("block info reply was missing device list"));
+ goto cleanup;
+ }
+
+ for (i = 0; i < virJSONValueArraySize(devices); i++) {
+ virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
+ const char *thisdev;
+
+ if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("block info device entry was not in expected format"));
+ goto cleanup;
+ }
+
+ if ((thisdev = virJSONValueObjectGetString(dev, "device")) == NULL) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("block info device entry was not in expected format"));
+ goto cleanup;
+ }
+
+ if (STRPREFIX(thisdev, QEMU_DRIVE_HOST_PREFIX))
+ thisdev += strlen(QEMU_DRIVE_HOST_PREFIX);
+
+ if (STRNEQ(thisdev, devname))
+ continue;
+
+ found = true;
+ if (virJSONValueObjectGetBoolean(dev, "removable", &info->removable) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s value"),
+ "removable");
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetBoolean(dev, "locked", &info->locked) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s value"),
+ "locked");
+ goto cleanup;
+ }
+
+ /* Don't check for success here, because 'tray-open' is presented iff
+ * medium is ejected.
+ */
+ virJSONValueObjectGetBoolean(dev, "tray-open", &info->tray_open);
+
+ break;
+ }
+
+ if (!found) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot find info for device '%s'"),
+ devname);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ return ret;
+}
+
+
int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
const char *devname,
long long *rd_req,
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index dfeba7e..24d6aec 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -60,6 +60,9 @@ int qemuMonitorJSONGetBalloonInfo(qemuMonitorPtr mon,
int qemuMonitorJSONGetMemoryStats(qemuMonitorPtr mon,
virDomainMemoryStatPtr stats,
unsigned int nr_stats);
+int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
+ const char *devname,
+ struct qemuDomainDiskInfo *info);
int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
const char *devname,
long long *rd_req,
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index 0b50ba2..50b9836 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -750,6 +750,96 @@ int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon,
}
+int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
+ const char *devname,
+ struct qemuDomainDiskInfo *info)
+{
+ char *reply = NULL;
+ int ret = -1;
+ char *dummy;
+ const char *p, *eol;
+ int devnamelen = strlen(devname);
+ int tmp;
+
+ if (qemuMonitorHMPCommand(mon, "info block", &reply) < 0) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ "%s", _("info block command failed"));
+ goto cleanup;
+ }
+
+ if (strstr(reply, "\ninfo ")) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s",
+ _("info block not supported by this qemu"));
+ goto cleanup;
+ }
+
+ /* The output looks like this:
+ * drive-ide0-0-0: removable=0 file=<path> ro=0 drv=raw encrypted=0
+ * drive-ide0-1-0: removable=1 locked=0 file=<path> ro=1 drv=raw encrypted=0
+ */
+ p = reply;
+
+ while (*p) {
+ if (STRPREFIX(p, QEMU_DRIVE_HOST_PREFIX))
+ p += strlen(QEMU_DRIVE_HOST_PREFIX);
+
+ if (STREQLEN(p, devname, devnamelen) &&
+ p[devnamelen] == ':' && p[devnamelen+1] == ' ') {
+
+ eol = strchr(p, '\n');
+ if (!eol)
+ eol = p + strlen(p);
+
+ p += devnamelen + 2; /*Skip to first label. */
+
+ while (*p) {
+ if (STRPREFIX(p, "removable=")) {
+ p += strlen("removable=");
+ if (virStrToLong_i(p, &dummy, 10, &tmp) == -1)
+ VIR_DEBUG("error reading removable: %s", p);
+ else
+ info->removable = p ? true : false;
+ } else if (STRPREFIX(p, "locked=")) {
+ p += strlen("locked=");
+ if (virStrToLong_i(p, &dummy, 10, &tmp) == -1)
+ VIR_DEBUG("error reading locked: %s", p);
+ else
+ info->locked = p ? true : false;
+ } else if (STRPREFIX(p, "tray_open=")) {
+ p += strlen("tray_open=");
+ if (virStrToLong_i(p, &dummy, 10, &tmp) == -1)
+ VIR_DEBUG("error reading tray_open: %s", p);
+ else
+ info->tray_open = p ? true : false;
+ } else {
+ /* ignore because we don't parse all options */
+ }
+
+ /* skip to next label */
+ p = strchr(p, ' ');
+ if (!p || p >= eol) break;
+ p++;
+ }
+
+ ret = 0;
+ goto cleanup;
+ }
+
+ /* skip to next line */
+ p = strchr(p, '\n');
+ if (!p) break;
+ p++;
+ }
+
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("no info for device '%s'"), devname);
+
+cleanup:
+ VIR_FREE(reply);
+ return ret;
+}
+
int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon,
const char *devname,
long long *rd_req,
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index 7cc3172..68e16b3 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -57,6 +57,9 @@ int qemuMonitorTextGetBalloonInfo(qemuMonitorPtr mon,
int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon,
virDomainMemoryStatPtr stats,
unsigned int nr_stats);
+int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
+ const char *devname,
+ struct qemuDomainDiskInfo *info);
int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon,
const char *devname,
long long *rd_req,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index f8a8475..7b5d10a 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2612,6 +2612,9 @@ qemuProcessReconnect(void *opaque)
if (qemuProcessFiltersInstantiate(conn, obj->def))
goto error;
+ if (qemuDomainCheckEjectableMedia(driver, obj) < 0)
+ goto error;
+
if (qemuProcessRecoverJob(driver, obj, conn, &oldjob) < 0)
goto error;
--
1.7.3.4
13 years, 2 months
[libvirt] [PATCH] virsh: describe attach-interface parameter target
by Daniel Veillard
This patch is based on a improvement suggested by Kazuhiro Kikuchi
of Fujitsu, it gives a description of the target parameter for that
command
* tools/virsh.pod: add description for target parameter of
attach-interface
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 6e3febb..ca37e57 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1239,6 +1239,10 @@ the default one.
I<model> allows to specify the model type.
I<persistent> indicates the changes will affect the next boot of the domain.
+B<Note>: the optional target value is the name of a device to be created
+as the back-end on the node. If not provided a device named "vnetN" or "vifN"
+will be created automatically.
+
=item B<detach-device> I<domain-id> I<FILE>
Detach a device from the domain, takes the same kind of XML descriptions
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
13 years, 2 months
[libvirt] [PATCH] qemu: Preserve fakeReboot flag in domain status
by Jiri Denemark
Thus, when libvirtd is restarted, it will know if a domain is supposed
to be killed or reset when it shuts down.
---
src/qemu/qemu_domain.c | 21 +++++++++++++++++++++
src/qemu/qemu_domain.h | 4 ++++
src/qemu/qemu_driver.c | 11 +++++------
src/qemu/qemu_process.c | 4 ++--
4 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 4023648..320a35c 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -302,6 +302,9 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
virBufferAddLit(buf, "/>\n");
}
+ if (priv->fakeReboot)
+ virBufferAsprintf(buf, " <fakereboot/>\n");
+
return 0;
}
@@ -445,6 +448,8 @@ static int qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
}
}
+ priv->fakeReboot = virXPathBoolean("boolean(./fakereboot)", ctxt) == 1;
+
return 0;
error:
@@ -1566,3 +1571,19 @@ qemuDomainRemoveInactive(struct qemud_driver *driver,
}
virDomainRemoveInactive(&driver->domains, vm);
}
+
+void
+qemuDomainSetFakeReboot(struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ bool value)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+
+ if (priv->fakeReboot == value)
+ return;
+
+ priv->fakeReboot = value;
+
+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
+ VIR_WARN("Failed to save status on vm %s", vm->def->name);
+}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 00cfa3a..3b09419 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -273,4 +273,8 @@ int qemuDomainSnapshotDiscardAllMetadata(struct qemud_driver *driver,
void qemuDomainRemoveInactive(struct qemud_driver *driver,
virDomainObjPtr vm);
+void qemuDomainSetFakeReboot(struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ bool value);
+
#endif /* __QEMU_DOMAIN_H__ */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0d0bea2..8cbb850 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1512,13 +1512,13 @@ static int qemuDomainShutdown(virDomainPtr dom) {
goto endjob;
}
+ qemuDomainSetFakeReboot(driver, vm, false);
+
priv = vm->privateData;
qemuDomainObjEnterMonitor(driver, vm);
ret = qemuMonitorSystemPowerdown(priv->mon);
qemuDomainObjExitMonitor(driver, vm);
- priv->fakeReboot = false;
-
endjob:
if (qemuDomainObjEndJob(driver, vm) == 0)
vm = NULL;
@@ -1575,7 +1575,8 @@ static int qemuDomainReboot(virDomainPtr dom, unsigned int flags) {
ret = qemuMonitorSystemPowerdown(priv->mon);
qemuDomainObjExitMonitor(driver, vm);
- priv->fakeReboot = true;
+ if (ret == 0)
+ qemuDomainSetFakeReboot(driver, vm, true);
endjob:
if (qemuDomainObjEndJob(driver, vm) == 0)
@@ -1616,7 +1617,6 @@ qemuDomainDestroyFlags(virDomainPtr dom,
virDomainObjPtr vm;
int ret = -1;
virDomainEventPtr event = NULL;
- qemuDomainObjPrivatePtr priv;
virCheckFlags(0, -1);
@@ -1630,8 +1630,7 @@ qemuDomainDestroyFlags(virDomainPtr dom,
goto cleanup;
}
- priv = vm->privateData;
- priv->fakeReboot = false;
+ qemuDomainSetFakeReboot(driver, vm, false);
/* Although qemuProcessStop does this already, there may
* be an outstanding job active. We want to make sure we
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 106a47c..4c6b4a4 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -442,7 +442,7 @@ qemuProcessShutdownOrReboot(virDomainObjPtr vm)
priv->gotShutdown = true;
if (priv->fakeReboot) {
- priv->fakeReboot = false;
+ qemuDomainSetFakeReboot(qemu_driver, vm, false);
virDomainObjRef(vm);
virThread th;
if (virThreadCreate(&th,
@@ -2846,7 +2846,7 @@ int qemuProcessStart(virConnectPtr conn,
goto cleanup;
vm->def->id = driver->nextvmid++;
- priv->fakeReboot = false;
+ qemuDomainSetFakeReboot(driver, vm, false);
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_UNKNOWN);
/* Run an early hook to set-up missing devices */
--
1.7.6.1
13 years, 2 months
[libvirt] [libvirt-glib] Remove redundant 'Config' in GIR identifiers
by Zeeshan Ali (Khattak)
From: "Zeeshan Ali (Khattak)" <zeeshanak(a)gnome.org>
libvirt-gconfig is in a separate namespace than libvirt-gobject so there
is not reason to expose 'Config' part of identifiers to high-level
languages.
---
libvirt-gconfig/Makefile.am | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/libvirt-gconfig/Makefile.am b/libvirt-gconfig/Makefile.am
index fbcb7ba..6f1c628 100644
--- a/libvirt-gconfig/Makefile.am
+++ b/libvirt-gconfig/Makefile.am
@@ -64,7 +64,7 @@ LibvirtGConfig-1.0.gir: libvirt-gconfig-1.0.la $(G_IR_SCANNER) Makefile.am
--namespace LibvirtGConfig \
--nsversion 1.0 \
--include GObject-2.0 \
- --identifier-prefix=GVir \
+ --identifier-prefix=GVirConfig \
--symbol-prefix=gvir \
--library=$(builddir)/libvirt-gconfig-1.0.la \
--output $@ \
--
1.7.6.2
13 years, 2 months
[libvirt] [PATCH] qemu: Init the pci device before reattachment
by Osier Yang
This patch is just like commit 2ce90ea296, to init the member of
pciDevice before reattachment, otherwise the device won't be unbound
from pci_stub, and won't get the original driver (no probing).
---
src/qemu/qemu_hostdev.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
index 6f77717..74c817c 100644
--- a/src/qemu/qemu_hostdev.c
+++ b/src/qemu/qemu_hostdev.c
@@ -292,6 +292,7 @@ void qemuDomainReAttachHostdevDevices(struct qemud_driver *driver,
for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ pciDeviceReAttachInit(dev);
qemuReattachPciDevice(dev, driver);
}
--
1.7.6
13 years, 2 months
[libvirt] [PATCH] qemu: Finish domain shutdown on reconnect
by Jiri Denemark
If a domain started with -no-shutdown shuts down while libvirtd is not
running, it will be seen as paused when libvirtd reconnects to it. Use
the paused reason to detect if a domain was stopped because of shutdown
and finish the process just as if a SHUTDOWN event is delivered from
qemu.
---
src/qemu/qemu_process.c | 50 ++++++++++++++++++++++++++++++++--------------
1 files changed, 35 insertions(+), 15 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 21e6fbf..106a47c 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -429,18 +429,15 @@ cleanup:
}
-static int
-qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
- virDomainObjPtr vm)
+static void
+qemuProcessShutdownOrReboot(virDomainObjPtr vm)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
- VIR_DEBUG("vm=%p", vm);
- virDomainObjLock(vm);
if (priv->gotShutdown) {
VIR_DEBUG("Ignoring repeated SHUTDOWN event from domain %s",
vm->def->name);
- goto cleanup;
+ return;
}
priv->gotShutdown = true;
@@ -454,16 +451,23 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
vm) < 0) {
VIR_ERROR(_("Failed to create reboot thread, killing domain"));
qemuProcessKill(vm, true);
- if (virDomainObjUnref(vm) == 0)
- vm = NULL;
+ /* Safe to ignore value since ref count was incremented above */
+ ignore_value(virDomainObjUnref(vm));
}
} else {
qemuProcessKill(vm, true);
}
+}
-cleanup:
- if (vm)
- virDomainObjUnlock(vm);
+static int
+qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+ virDomainObjPtr vm)
+{
+ VIR_DEBUG("vm=%p", vm);
+
+ virDomainObjLock(vm);
+ qemuProcessShutdownOrReboot(vm);
+ virDomainObjUnlock(vm);
return 0;
}
@@ -2572,6 +2576,8 @@ qemuProcessReconnect(void *opaque)
qemuDomainObjPrivatePtr priv;
virConnectPtr conn = data->conn;
struct qemuDomainJobObj oldjob;
+ int state;
+ int reason;
memcpy(&oldjob, &data->oldjob, sizeof(oldjob));
@@ -2603,7 +2609,8 @@ qemuProcessReconnect(void *opaque)
if (qemuProcessUpdateState(driver, obj) < 0)
goto error;
- if (virDomainObjGetState(obj, NULL) == VIR_DOMAIN_SHUTOFF) {
+ state = virDomainObjGetState(obj, &reason);
+ if (state == VIR_DOMAIN_SHUTOFF) {
VIR_DEBUG("Domain '%s' wasn't fully started yet, killing it",
obj->def->name);
goto error;
@@ -2618,6 +2625,18 @@ qemuProcessReconnect(void *opaque)
&priv->qemuCaps) < 0)
goto error;
+ /* In case the domain was paused for shutdown while we were not running,
+ * we need to finish the shutdown process. And we need to do it after
+ * we have qemuCaps filled in.
+ */
+ if (state == VIR_DOMAIN_PAUSED
+ && reason == VIR_DOMAIN_PAUSED_SHUTTING_DOWN) {
+ VIR_DEBUG("Domain %s shut down while we were not running;"
+ " finishing shutdown sequence", obj->def->name);
+ qemuProcessShutdownOrReboot(obj);
+ goto endjob;
+ }
+
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
priv->persistentAddrs = 1;
@@ -2647,12 +2666,13 @@ qemuProcessReconnect(void *opaque)
if (obj->def->id >= driver->nextvmid)
driver->nextvmid = obj->def->id + 1;
- if (virDomainObjUnref(obj) > 0)
- virDomainObjUnlock(obj);
-
+endjob:
if (qemuDomainObjEndJob(driver, obj) == 0)
obj = NULL;
+ if (obj && virDomainObjUnref(obj) > 0)
+ virDomainObjUnlock(obj);
+
qemuDriverUnlock(driver);
virConnectClose(conn);
--
1.7.6.1
13 years, 2 months
[libvirt] [PATCH] qemu: Check domain status details when reconnecting monitor
by Jiri Denemark
Current qemu is able to give us detailed domain status (not just if it
is running or not) which we can translate into a status reason.
---
src/qemu/qemu_monitor.c | 66 +++++++++++++++++++++++++++++++++++++++--
src/qemu/qemu_monitor.h | 25 +++++++++++++++-
src/qemu/qemu_monitor_json.c | 15 +++++++++-
src/qemu/qemu_monitor_json.h | 4 ++-
src/qemu/qemu_monitor_text.c | 20 ++++++++++++-
src/qemu/qemu_monitor_text.h | 4 ++-
src/qemu/qemu_process.c | 15 ++++++----
7 files changed, 134 insertions(+), 15 deletions(-)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index b4c43ae..6e84131 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -81,6 +81,12 @@ VIR_ENUM_IMPL(qemuMonitorMigrationStatus,
QEMU_MONITOR_MIGRATION_STATUS_LAST,
"inactive", "active", "completed", "failed", "cancelled")
+VIR_ENUM_IMPL(qemuMonitorVMStatus,
+ QEMU_MONITOR_VM_STATUS_LAST,
+ "debug", "inmigrate", "internal-error", "io-error", "paused",
+ "postmigrate", "prelaunch", "finish-migrate", "restore-vm",
+ "running", "save-vm", "shutdown", "watchdog")
+
char *qemuMonitorEscapeArg(const char *in)
{
int len = 0;
@@ -1059,10 +1065,12 @@ qemuMonitorStopCPUs(qemuMonitorPtr mon)
int
-qemuMonitorGetStatus(qemuMonitorPtr mon, bool *running)
+qemuMonitorGetStatus(qemuMonitorPtr mon,
+ bool *running,
+ virDomainPausedReason *reason)
{
int ret;
- VIR_DEBUG("mon=%p, running=%p", mon, running);
+ VIR_DEBUG("mon=%p, running=%p, reason=%p", mon, running, reason);
if (!mon || !running) {
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
@@ -1071,9 +1079,9 @@ qemuMonitorGetStatus(qemuMonitorPtr mon, bool *running)
}
if (mon->json)
- ret = qemuMonitorJSONGetStatus(mon, running);
+ ret = qemuMonitorJSONGetStatus(mon, running, reason);
else
- ret = qemuMonitorTextGetStatus(mon, running);
+ ret = qemuMonitorTextGetStatus(mon, running, reason);
return ret;
}
@@ -2553,3 +2561,53 @@ int qemuMonitorBlockJob(qemuMonitorPtr mon,
ret = qemuMonitorTextBlockJob(mon, device, bandwidth, info, mode);
return ret;
}
+
+int qemuMonitorVMStatusToPausedReason(const char *status)
+{
+ int st;
+
+ if (!status)
+ return VIR_DOMAIN_PAUSED_UNKNOWN;
+
+ if ((st = qemuMonitorVMStatusTypeFromString(status)) < 0) {
+ VIR_WARN("Qemu reported unknown VM status: '%s'", status);
+ return VIR_DOMAIN_PAUSED_UNKNOWN;
+ }
+
+ switch ((qemuMonitorVMStatus) st) {
+ case QEMU_MONITOR_VM_STATUS_DEBUG:
+ case QEMU_MONITOR_VM_STATUS_INTERNAL_ERROR:
+ case QEMU_MONITOR_VM_STATUS_RESTORE_VM:
+ return VIR_DOMAIN_PAUSED_UNKNOWN;
+
+ case QEMU_MONITOR_VM_STATUS_INMIGRATE:
+ case QEMU_MONITOR_VM_STATUS_POSTMIGRATE:
+ case QEMU_MONITOR_VM_STATUS_FINISH_MIGRATE:
+ return VIR_DOMAIN_PAUSED_MIGRATION;
+
+ case QEMU_MONITOR_VM_STATUS_IO_ERROR:
+ return VIR_DOMAIN_PAUSED_IOERROR;
+
+ case QEMU_MONITOR_VM_STATUS_PAUSED:
+ case QEMU_MONITOR_VM_STATUS_PRELAUNCH:
+ return VIR_DOMAIN_PAUSED_USER;
+
+ case QEMU_MONITOR_VM_STATUS_RUNNING:
+ VIR_WARN("Qemu reports the guest is paused but status is 'running'");
+ return VIR_DOMAIN_PAUSED_UNKNOWN;
+
+ case QEMU_MONITOR_VM_STATUS_SAVE_VM:
+ return VIR_DOMAIN_PAUSED_SAVE;
+
+ case QEMU_MONITOR_VM_STATUS_SHUTDOWN:
+ return VIR_DOMAIN_PAUSED_SHUTTING_DOWN;
+
+ case QEMU_MONITOR_VM_STATUS_WATCHDOG:
+ return VIR_DOMAIN_PAUSED_WATCHDOG;
+
+ /* unreachable from this point on */
+ case QEMU_MONITOR_VM_STATUS_LAST:
+ ;
+ }
+ return VIR_DOMAIN_PAUSED_UNKNOWN;
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 477767f..a64c2c3 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -198,7 +198,30 @@ int qemuMonitorEmitBlockJob(qemuMonitorPtr mon,
int qemuMonitorStartCPUs(qemuMonitorPtr mon,
virConnectPtr conn);
int qemuMonitorStopCPUs(qemuMonitorPtr mon);
-int qemuMonitorGetStatus(qemuMonitorPtr mon, bool *running);
+
+typedef enum {
+ QEMU_MONITOR_VM_STATUS_DEBUG,
+ QEMU_MONITOR_VM_STATUS_INMIGRATE,
+ QEMU_MONITOR_VM_STATUS_INTERNAL_ERROR,
+ QEMU_MONITOR_VM_STATUS_IO_ERROR,
+ QEMU_MONITOR_VM_STATUS_PAUSED,
+ QEMU_MONITOR_VM_STATUS_POSTMIGRATE,
+ QEMU_MONITOR_VM_STATUS_PRELAUNCH,
+ QEMU_MONITOR_VM_STATUS_FINISH_MIGRATE,
+ QEMU_MONITOR_VM_STATUS_RESTORE_VM,
+ QEMU_MONITOR_VM_STATUS_RUNNING,
+ QEMU_MONITOR_VM_STATUS_SAVE_VM,
+ QEMU_MONITOR_VM_STATUS_SHUTDOWN,
+ QEMU_MONITOR_VM_STATUS_WATCHDOG,
+
+ QEMU_MONITOR_VM_STATUS_LAST
+} qemuMonitorVMStatus;
+VIR_ENUM_DECL(qemuMonitorVMStatus)
+int qemuMonitorVMStatusToPausedReason(const char *status);
+
+int qemuMonitorGetStatus(qemuMonitorPtr mon,
+ bool *running,
+ virDomainPausedReason *reason);
int qemuMonitorSystemReset(qemuMonitorPtr mon);
int qemuMonitorSystemPowerdown(qemuMonitorPtr mon);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index e38c2ed..b720617 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -896,13 +896,19 @@ qemuMonitorJSONStopCPUs(qemuMonitorPtr mon)
int
-qemuMonitorJSONGetStatus(qemuMonitorPtr mon, bool *running)
+qemuMonitorJSONGetStatus(qemuMonitorPtr mon,
+ bool *running,
+ virDomainPausedReason *reason)
{
int ret;
+ const char *status;
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
virJSONValuePtr data;
+ if (reason)
+ *reason = VIR_DOMAIN_PAUSED_UNKNOWN;
+
if (!(cmd = qemuMonitorJSONMakeCommand("query-status", NULL)))
return -1;
@@ -928,6 +934,13 @@ qemuMonitorJSONGetStatus(qemuMonitorPtr mon, bool *running)
goto cleanup;
}
+ if ((status = virJSONValueObjectGetString(data, "status"))) {
+ if (!*running && reason)
+ *reason = qemuMonitorVMStatusToPausedReason(status);
+ } else if (!*running) {
+ VIR_DEBUG("query-status reply was missing status details");
+ }
+
ret = 0;
cleanup:
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 673444f..1a40716 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -46,7 +46,9 @@ int qemuMonitorJSONCheckHMP(qemuMonitorPtr mon);
int qemuMonitorJSONStartCPUs(qemuMonitorPtr mon,
virConnectPtr conn);
int qemuMonitorJSONStopCPUs(qemuMonitorPtr mon);
-int qemuMonitorJSONGetStatus(qemuMonitorPtr mon, bool *running);
+int qemuMonitorJSONGetStatus(qemuMonitorPtr mon,
+ bool *running,
+ virDomainPausedReason *reason);
int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon);
int qemuMonitorJSONSystemReset(qemuMonitorPtr mon);
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index cedf582..57e74a8 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -392,11 +392,16 @@ qemuMonitorTextStopCPUs(qemuMonitorPtr mon) {
int
-qemuMonitorTextGetStatus(qemuMonitorPtr mon, bool *running)
+qemuMonitorTextGetStatus(qemuMonitorPtr mon,
+ bool *running,
+ virDomainPausedReason *reason)
{
char *reply;
int ret = -1;
+ if (reason)
+ *reason = VIR_DOMAIN_PAUSED_UNKNOWN;
+
if (qemuMonitorHMPCommand(mon, "info status", &reply) < 0) {
qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("cannot get status info"));
@@ -406,6 +411,19 @@ qemuMonitorTextGetStatus(qemuMonitorPtr mon, bool *running)
if (strstr(reply, "running")) {
*running = true;
} else if (strstr(reply, "paused")) {
+ char *status;
+
+ if ((status = strchr(reply, '('))) {
+ char *end = strchr(status, ')');
+ if (end)
+ *end = '\0';
+ else
+ status = NULL;
+ }
+ if (!status)
+ VIR_DEBUG("info status was missing status details");
+ else if (reason)
+ *reason = qemuMonitorVMStatusToPausedReason(status);
*running = false;
} else {
qemuReportError(VIR_ERR_OPERATION_FAILED,
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index 4651a17..207001d 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -43,7 +43,9 @@ int qemuMonitorTextCommandWithFd(qemuMonitorPtr mon,
int qemuMonitorTextStartCPUs(qemuMonitorPtr mon,
virConnectPtr conn);
int qemuMonitorTextStopCPUs(qemuMonitorPtr mon);
-int qemuMonitorTextGetStatus(qemuMonitorPtr mon, bool *running);
+int qemuMonitorTextGetStatus(qemuMonitorPtr mon,
+ bool *running,
+ virDomainPausedReason *reason);
int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon);
int qemuMonitorTextSystemReset(qemuMonitorPtr mon);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index c8f22e2..21e6fbf 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2321,11 +2321,12 @@ qemuProcessUpdateState(struct qemud_driver *driver, virDomainObjPtr vm)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
virDomainState state;
+ virDomainPausedReason reason;
bool running;
int ret;
qemuDomainObjEnterMonitorWithDriver(driver, vm);
- ret = qemuMonitorGetStatus(priv->mon, &running);
+ ret = qemuMonitorGetStatus(priv->mon, &running, &reason);
qemuDomainObjExitMonitorWithDriver(driver, vm);
if (ret < 0 || !virDomainObjIsActive(vm))
@@ -2339,9 +2340,10 @@ qemuProcessUpdateState(struct qemud_driver *driver, virDomainObjPtr vm)
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
VIR_DOMAIN_RUNNING_UNPAUSED);
} else if (state == VIR_DOMAIN_RUNNING && !running) {
- VIR_DEBUG("Domain %s was paused while its monitor was disconnected;"
- " changing state to paused", vm->def->name);
- virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_UNKNOWN);
+ VIR_DEBUG("Domain %s was paused (%s) while its monitor was"
+ " disconnected; changing state to paused",
+ vm->def->name, virDomainPausedReasonTypeToString(reason));
+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, reason);
} else if (state == VIR_DOMAIN_SHUTOFF && running) {
VIR_DEBUG("Domain %s finished booting; changing state to running",
vm->def->name);
@@ -3470,6 +3472,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
char *timestamp;
qemuDomainObjPrivatePtr priv = vm->privateData;
bool running = true;
+ virDomainPausedReason reason;
virSecurityLabelPtr seclabel = NULL;
VIR_DEBUG("Beginning VM attach process");
@@ -3599,7 +3602,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
qemuDomainObjExitMonitorWithDriver(driver, vm);
goto cleanup;
}
- if (qemuMonitorGetStatus(priv->mon, &running) < 0) {
+ if (qemuMonitorGetStatus(priv->mon, &running, &reason) < 0) {
qemuDomainObjExitMonitorWithDriver(driver, vm);
goto cleanup;
}
@@ -3616,7 +3619,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
VIR_DOMAIN_RUNNING_UNPAUSED);
else
- virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_UNKNOWN);
+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, reason);
VIR_DEBUG("Writing domain status to disk");
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
--
1.7.6.1
13 years, 2 months
[libvirt] [PATCH] qemu: Always remove domain object if MigratePrepare fails
by Jiri Denemark
If migration failed in Prepare phase after virDomainAssignDef and before
a job is started, the domain object was not properly removed.
---
src/qemu/qemu_migration.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 0a5a13d..ea49093 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1178,8 +1178,12 @@ cleanup:
virDomainDefFree(def);
VIR_FORCE_CLOSE(dataFD[0]);
VIR_FORCE_CLOSE(dataFD[1]);
- if (vm)
- virDomainObjUnlock(vm);
+ if (vm) {
+ if (vm->persistent)
+ virDomainObjUnlock(vm);
+ else
+ qemuDomainRemoveInactive(driver, vm);
+ }
if (event)
qemuDomainEventQueue(driver, event);
qemuMigrationCookieFree(mig);
@@ -1188,9 +1192,6 @@ cleanup:
endjob:
if (qemuMigrationJobFinish(driver, vm) == 0) {
vm = NULL;
- } else if (!vm->persistent) {
- qemuDomainRemoveInactive(driver, vm);
- vm = NULL;
}
goto cleanup;
}
--
1.7.6.1
13 years, 2 months
[libvirt] [libvirt-glib] Refactor two very huge functions a bit
by Zeeshan Ali (Khattak)
From: "Zeeshan Ali (Khattak)" <zeeshanak(a)gnome.org>
---
libvirt-gobject/libvirt-gobject-connection.c | 126 ++++++++++++++------------
1 files changed, 69 insertions(+), 57 deletions(-)
diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c
index f97b50a..c0c47da 100644
--- a/libvirt-gobject/libvirt-gobject-connection.c
+++ b/libvirt-gobject/libvirt-gobject-connection.c
@@ -374,6 +374,51 @@ void gvir_connection_close(GVirConnection *conn)
g_signal_emit_by_name(conn, "vir-connection-closed");
}
+typedef gint (* CountFunction) (virConnectPtr vconn);
+typedef gint (* ListFunction) (virConnectPtr vconn, gchar **lst, gint max);
+
+static gchar ** fetch_list(virConnectPtr vconn,
+ const char *name,
+ CountFunction count_func,
+ ListFunction list_func,
+ GCancellable *cancellable,
+ gint *length,
+ GError **err)
+{
+ gchar **lst = NULL;
+ gint n = 0;
+ gint i;
+
+ if ((n = count_func(vconn)) < 0) {
+ *err = gvir_error_new(GVIR_CONNECTION_ERROR,
+ 0,
+ "Unable to count %s", name);
+ goto error;
+ }
+
+ if (n) {
+ if (g_cancellable_set_error_if_cancelled(cancellable, err))
+ goto error;
+
+ lst = g_new(gchar *, n);
+ if ((n = list_func(vconn, lst, n)) < 0) {
+ *err = gvir_error_new(GVIR_CONNECTION_ERROR,
+ 0,
+ "Unable to list %s %d", name, n);
+ goto error;
+ }
+ }
+
+ *length = n;
+ return lst;
+
+error:
+ for (i = 0 ; i < n; i++)
+ g_free(lst[i]);
+ g_free(lst);
+ return NULL;
+}
+
/**
* gvir_connection_fetch_domains:
* @conn: the connection
@@ -431,25 +476,15 @@ gboolean gvir_connection_fetch_domains(GVirConnection *conn,
if (g_cancellable_set_error_if_cancelled(cancellable, err))
goto cleanup;
- if ((ninactive = virConnectNumOfDefinedDomains(vconn)) < 0) {
- *err = gvir_error_new(GVIR_CONNECTION_ERROR,
- 0,
- "Unable to count domains");
+ inactive = fetch_list(vconn,
+ "Domains",
+ virConnectNumOfDefinedDomains,
+ virConnectListDefinedDomains,
+ cancellable,
+ &ninactive,
+ err);
+ if (*err != NULL)
goto cleanup;
- }
-
- if (ninactive) {
- if (g_cancellable_set_error_if_cancelled(cancellable, err))
- goto cleanup;
-
- inactive = g_new(gchar *, ninactive);
- if ((ninactive = virConnectListDefinedDomains(vconn, inactive, ninactive)) < 0) {
- *err = gvir_error_new(GVIR_CONNECTION_ERROR,
- 0,
- "Unable to list domains %d", ninactive);
- goto cleanup;
- }
- }
doms = g_hash_table_new_full(g_str_hash,
g_str_equal,
@@ -544,51 +579,28 @@ gboolean gvir_connection_fetch_storage_pools(GVirConnection *conn,
if (g_cancellable_set_error_if_cancelled(cancellable, err))
goto cleanup;
- if ((nactive = virConnectNumOfStoragePools(vconn)) < 0) {
- *err = gvir_error_new(GVIR_CONNECTION_ERROR,
- 0,
- "Unable to count pools");
+ active = fetch_list(vconn,
+ "Storage Pools",
+ virConnectNumOfStoragePools,
+ virConnectListStoragePools,
+ cancellable,
+ &nactive,
+ err);
+ if (*err != NULL)
goto cleanup;
- }
- if (nactive) {
- if (g_cancellable_set_error_if_cancelled(cancellable, err))
- goto cleanup;
-
- active = g_new(gchar *, nactive);
- if ((nactive = virConnectListStoragePools(vconn,
- active,
- nactive)) < 0) {
- *err = gvir_error_new(GVIR_CONNECTION_ERROR,
- 0,
- "Unable to list pools");
- goto cleanup;
- }
- }
if (g_cancellable_set_error_if_cancelled(cancellable, err))
goto cleanup;
- if ((ninactive = virConnectNumOfDefinedStoragePools(vconn)) < 0) {
- *err = gvir_error_new(GVIR_CONNECTION_ERROR,
- 0,
- "Unable to count pools");
+ inactive = fetch_list(vconn,
+ "Storage Pools",
+ virConnectNumOfDefinedStoragePools,
+ virConnectListDefinedStoragePools,
+ cancellable,
+ &ninactive,
+ err);
+ if (*err != NULL)
goto cleanup;
- }
-
- if (ninactive) {
- if (g_cancellable_set_error_if_cancelled(cancellable, err))
- goto cleanup;
-
- inactive = g_new(gchar *, ninactive);
- if ((ninactive = virConnectListDefinedStoragePools(vconn,
- inactive,
- ninactive)) < 0) {
- *err = gvir_error_new(GVIR_CONNECTION_ERROR,
- 0,
- "Unable to list pools %d", ninactive);
- goto cleanup;
- }
- }
pools = g_hash_table_new_full(g_str_hash,
g_str_equal,
--
1.7.6.2
13 years, 2 months
[libvirt] [libvirt-glib] Plug a leak
by Zeeshan Ali (Khattak)
From: "Zeeshan Ali (Khattak)" <zeeshanak(a)gnome.org>
---
libvirt-gobject/libvirt-gobject-connection.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c
index 074fe53..f97b50a 100644
--- a/libvirt-gobject/libvirt-gobject-connection.c
+++ b/libvirt-gobject/libvirt-gobject-connection.c
@@ -645,6 +645,8 @@ gboolean gvir_connection_fetch_storage_pools(GVirConnection *conn,
ret = TRUE;
cleanup:
+ for (i = 0 ; i < nactive ; i++)
+ g_free(active[i]);
g_free(active);
for (i = 0 ; i < ninactive ; i++)
g_free(inactive[i]);
--
1.7.6.2
13 years, 2 months