[libvirt] [PATCH v2] parallels: add block device statistics to driver
by Nikolay Shirokovskiy
Statistics provided through PCS SDK. As we have only async interface in SDK we
need to be subscribed to statistics in order to get it. Trivial solution on
every stat request to subscribe, wait event and then unsubscribe will lead to
significant delays in case of a number of successive requests, as the event
will be delivered on next PCS server notify cycle. On the other hand we don't
want to keep unnesessary subscribtion. So we take an hibrid solution to
subcsribe on first request and then keep a subscription while requests are
active. We populate cache of statistics on subscribtion events and use this
cache to serve libvirts requests.
* Cache details.
Cache is just handle to last arrived event, we call this cache
as if this handle is valid it is used to serve synchronous
statistics requests. We use number of successive events count
to detect that user lost interest to statistics. We reset this
count to 0 on every request. If more than PARALLELS_STATISTICS_DROP_COUNT
successive events arrive we unsubscribe. Special value of -1
of this counter is used to differentiate between subscribed/unsubscribed state
to protect from delayed events.
Values of RALLELS_STATISTICS_DROP_COUNT and PARALLELS_STATISTICS_TIMEOUT are
just drop-ins, choosen without special consideration.
* Thread safety issues
Use parallelsDomObjFromDomainRef in parallelsDomainBlockStats as
we could wait on domain lock down on stack in prlsdkGetStatsParam
and if we won't keep reference we could get dangling pointer
on return from wait.
Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy(a)parallels.com>
---
src/parallels/parallels_driver.c | 106 ++++++++++++++++++++++
src/parallels/parallels_sdk.c | 183 ++++++++++++++++++++++++++++++++++++++
src/parallels/parallels_sdk.h | 2 +
src/parallels/parallels_utils.c | 28 ++++++
src/parallels/parallels_utils.h | 18 ++++
5 files changed, 337 insertions(+), 0 deletions(-)
diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
index 4b87213..33c112e 100644
--- a/src/parallels/parallels_driver.c
+++ b/src/parallels/parallels_driver.c
@@ -51,6 +51,7 @@
#include "nodeinfo.h"
#include "virstring.h"
#include "cpu/cpu.h"
+#include "virtypedparam.h"
#include "parallels_driver.h"
#include "parallels_utils.h"
@@ -1179,6 +1180,109 @@ parallelsDomainGetMaxMemory(virDomainPtr domain)
return ret;
}
+static int
+parallelsDomainBlockStats(virDomainPtr domain, const char *path,
+ virDomainBlockStatsPtr stats)
+{
+ virDomainObjPtr dom = NULL;
+ int ret = -1;
+ size_t i;
+ int idx;
+
+ if (!(dom = parallelsDomObjFromDomainRef(domain)))
+ return -1;
+
+ if (*path) {
+ if ((idx = virDomainDiskIndexByName(dom->def, path, false)) < 0) {
+ virReportError(VIR_ERR_INVALID_ARG, _("invalid path: %s"), path);
+ goto cleanup;
+ }
+ if (prlsdkGetBlockStats(dom, dom->def->disks[idx], stats) < 0)
+ goto cleanup;
+ } else {
+ virDomainBlockStatsStruct s;
+
+#define PARALLELS_ZERO_STATS(VAR, TYPE, NAME) \
+ stats->VAR = 0;
+
+ PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_ZERO_STATS)
+
+#undef PARALLELS_ZERO_STATS
+
+ for (i = 0; i < dom->def->ndisks; i++) {
+ if (prlsdkGetBlockStats(dom, dom->def->disks[i], &s) < 0)
+ goto cleanup;
+
+#define PARALLELS_SUM_STATS(VAR, TYPE, NAME) \
+ if (s.VAR != -1) \
+ stats->VAR += s.VAR;
+
+ PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_SUM_STATS)
+
+#undef PARALLELS_SUM_STATS
+ }
+ }
+ stats->errs = -1;
+ ret = 0;
+
+ cleanup:
+ if (dom)
+ virDomainObjEndAPI(&dom);
+
+ return ret;
+}
+
+static int
+parallelsDomainBlockStatsFlags(virDomainPtr domain,
+ const char *path,
+ virTypedParameterPtr params,
+ int *nparams,
+ unsigned int flags)
+{
+ virDomainBlockStatsStruct stats;
+ int ret = -1;
+ size_t i;
+
+ virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+ /* We don't return strings, and thus trivially support this flag. */
+ flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
+
+ if (parallelsDomainBlockStats(domain, path, &stats) < 0)
+ goto cleanup;
+
+ if (*nparams == 0) {
+#define PARALLELS_COUNT_STATS(VAR, TYPE, NAME) \
+ if ((stats.VAR) != -1) \
+ ++*nparams;
+
+ PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_COUNT_STATS)
+
+#undef PARALLELS_COUNT_STATS
+ ret = 0;
+ goto cleanup;
+ }
+
+ i = 0;
+#define PARALLELS_BLOCK_STATS_ASSIGN_PARAM(VAR, TYPE, NAME) \
+ if (i < *nparams && (stats.VAR) != -1) { \
+ if (virTypedParameterAssign(params + i, TYPE, \
+ VIR_TYPED_PARAM_LLONG, (stats.VAR)) < 0) \
+ goto cleanup; \
+ i++; \
+ }
+
+ PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_BLOCK_STATS_ASSIGN_PARAM)
+
+#undef PARALLELS_BLOCK_STATS_ASSIGN_PARAM
+
+ *nparams = i;
+ ret = 0;
+
+ cleanup:
+ return ret;
+}
+
+
static virHypervisorDriver parallelsDriver = {
.name = "Parallels",
.connectOpen = parallelsConnectOpen, /* 0.10.0 */
@@ -1228,6 +1332,8 @@ static virHypervisorDriver parallelsDriver = {
.domainManagedSave = parallelsDomainManagedSave, /* 1.2.14 */
.domainManagedSaveRemove = parallelsDomainManagedSaveRemove, /* 1.2.14 */
.domainGetMaxMemory = parallelsDomainGetMaxMemory, /* 1.2.15 */
+ .domainBlockStats = parallelsDomainBlockStats, /* 1.2.17 */
+ .domainBlockStatsFlags = parallelsDomainBlockStatsFlags, /* 1.2.17 */
};
static virConnectDriver parallelsConnectDriver = {
diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c
index d5a9790..c2aae3b 100644
--- a/src/parallels/parallels_sdk.c
+++ b/src/parallels/parallels_sdk.c
@@ -21,6 +21,7 @@
*/
#include <config.h>
+#include <stdarg.h>
#include "virerror.h"
#include "viralloc.h"
@@ -29,6 +30,7 @@
#include "virlog.h"
#include "datatypes.h"
#include "domain_conf.h"
+#include "virtime.h"
#include "parallels_sdk.h"
@@ -407,6 +409,8 @@ prlsdkDomObjFreePrivate(void *p)
return;
PrlHandle_Free(pdom->sdkdom);
+ PrlHandle_Free(pdom->cache.stats);
+ virCondDestroy(&pdom->cache.cond);
VIR_FREE(pdom->uuid);
VIR_FREE(pdom->home);
VIR_FREE(p);
@@ -1260,6 +1264,13 @@ prlsdkLoadDomain(parallelsConnPtr privconn,
* to NULL temporarily */
pdom->uuid = NULL;
+ pdom->cache.stats = PRL_INVALID_HANDLE;
+ pdom->cache.count = -1;
+ if (virCondInit(&pdom->cache.cond) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot initialize condition"));
+ goto error;
+ }
+
if (prlsdkGetDomainIds(sdkdom, &def->name, def->uuid) < 0)
goto error;
@@ -1636,6 +1647,49 @@ prlsdkHandleVmRemovedEvent(parallelsConnPtr privconn,
}
static PRL_RESULT
+prlsdkHandlePerfEvent(parallelsConnPtr privconn,
+ PRL_HANDLE event,
+ unsigned char *uuid)
+{
+ virDomainObjPtr dom = NULL;
+ parallelsDomObjPtr privdom = NULL;
+ PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+ dom = virDomainObjListFindByUUID(privconn->domains, uuid);
+ if (dom == NULL)
+ goto cleanup;
+ privdom = dom->privateData;
+
+ // delayed event after unsubscribe
+ if (privdom->cache.count == -1)
+ goto cleanup;
+
+ PrlHandle_Free(privdom->cache.stats);
+ privdom->cache.stats = PRL_INVALID_HANDLE;
+
+ if (privdom->cache.count > 3) {
+ job = PrlVm_UnsubscribeFromPerfStats(privdom->sdkdom);
+ if (PRL_FAILED(waitJob(job)))
+ goto cleanup;
+ // change state to unsubscribed
+ privdom->cache.count = -1;
+ } else {
+ ++privdom->cache.count;
+ privdom->cache.stats = event;
+ // thus we get own of event handle
+ event = PRL_INVALID_HANDLE;
+ virCondSignal(&privdom->cache.cond);
+ }
+
+ cleanup:
+ PrlHandle_Free(event);
+ if (dom)
+ virObjectUnlock(dom);
+
+ return PRL_ERR_SUCCESS;
+}
+
+static PRL_RESULT
prlsdkHandleVmEvent(parallelsConnPtr privconn, PRL_HANDLE prlEvent)
{
PRL_RESULT pret;
@@ -1665,6 +1719,11 @@ prlsdkHandleVmEvent(parallelsConnPtr privconn, PRL_HANDLE prlEvent)
case PET_DSP_EVT_VM_UNREGISTERED:
return prlsdkHandleVmRemovedEvent(privconn, uuid);
break;
+ case PET_DSP_EVT_VM_PERFSTATS:
+ prlsdkHandlePerfEvent(privconn, prlEvent, uuid);
+ // above function takes own of event
+ prlEvent = PRL_INVALID_HANDLE;
+ break;
default:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Can't handle event of type %d"), prlEventType);
@@ -1714,6 +1773,7 @@ prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque)
return pret;
}
+
int prlsdkSubscribeToPCSEvents(parallelsConnPtr privconn)
{
PRL_RESULT pret = PRL_ERR_UNINITIALIZED;
@@ -3450,3 +3510,126 @@ prlsdkDomainManagedSaveRemove(virDomainObjPtr dom)
return 0;
}
+
+static int
+prlsdkExtractStatsParam(PRL_HANDLE sdkstats, const char *name, long long *val)
+{
+ PRL_HANDLE param = PRL_INVALID_HANDLE;
+ PRL_RESULT pret;
+ PRL_INT64 pval = 0;
+ int ret = -1;
+
+ pret = PrlEvent_GetParamByName(sdkstats, name, ¶m);
+ if (pret == PRL_ERR_NO_DATA) {
+ *val = -1;
+ ret = 0;
+ goto cleanup;
+ } else if (PRL_FAILED(pret)) {
+ logPrlError(pret);
+ goto cleanup;
+ }
+ pret = PrlEvtPrm_ToInt64(param, &pval);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ *val = pval;
+ ret = 0;
+
+ cleanup:
+ PrlHandle_Free(param);
+ return ret;
+}
+
+#define PARALLELS_STATISTICS_TIMEOUT (60 * 1000)
+
+static int
+prlsdkGetStatsParam(virDomainObjPtr dom, const char *name, long long *val)
+{
+ parallelsDomObjPtr privdom = dom->privateData;
+ PRL_HANDLE job = PRL_INVALID_HANDLE;
+ unsigned long long now;
+
+ if (privdom->cache.stats != PRL_INVALID_HANDLE) {
+ // reset count to keep subscribtion
+ privdom->cache.count = 0;
+ return prlsdkExtractStatsParam(privdom->cache.stats, name, val);
+ }
+
+ job = PrlVm_SubscribeToPerfStats(privdom->sdkdom, NULL);
+ if (PRL_FAILED(waitJob(job)))
+ goto error;
+
+ // change state to subscribed
+ privdom->cache.count = 0;
+ if (virTimeMillisNow(&now) < 0) {
+ virReportSystemError(errno, "%s", _("Unable to get current time"));
+ goto error;
+ }
+
+ while (privdom->cache.stats == PRL_INVALID_HANDLE) {
+ if (virCondWaitUntil(&privdom->cache.cond, &dom->parent.lock,
+ now + PARALLELS_STATISTICS_TIMEOUT) < 0) {
+ if (errno == ETIMEDOUT) {
+ virReportError(VIR_ERR_OPERATION_TIMEOUT, "%s",
+ _("Timeout on waiting statistics event."));
+ goto error;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to wait on monitor condition"));
+ goto error;
+ }
+ }
+ }
+
+ return prlsdkExtractStatsParam(privdom->cache.stats, name, val);
+ error:
+ return -1;
+}
+
+int
+prlsdkGetBlockStats(virDomainObjPtr dom, virDomainDiskDefPtr disk, virDomainBlockStatsPtr stats)
+{
+ virDomainDeviceDriveAddressPtr address;
+ int idx;
+ const char *prefix;
+ int ret = -1;
+ char *name = NULL;
+
+ address = &disk->info.addr.drive;
+ switch (disk->bus) {
+ case VIR_DOMAIN_DISK_BUS_IDE:
+ prefix = "ide";
+ idx = address->bus * 2 + address->unit;
+ break;
+ case VIR_DOMAIN_DISK_BUS_SATA:
+ prefix = "sata";
+ idx = address->unit;
+ break;
+ case VIR_DOMAIN_DISK_BUS_SCSI:
+ prefix = "scsi";
+ idx = address->unit;
+ break;
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unknown disk bus: %X"), disk->bus);
+ goto cleanup;
+ }
+
+
+#define PRLSDK_GET_STAT_PARAM(VAL, TYPE, NAME) \
+ if (virAsprintf(&name, "devices.%s%d.%s", prefix, idx, NAME) < 0) \
+ goto cleanup; \
+ if (prlsdkGetStatsParam(dom, name, &stats->VAL) < 0) \
+ goto cleanup; \
+ VIR_FREE(name);
+
+ PARALLELS_BLOCK_STATS_FOREACH(PRLSDK_GET_STAT_PARAM)
+
+#undef PRLSDK_GET_STAT_PARAM
+
+ ret = 0;
+
+ cleanup:
+
+ VIR_FREE(name);
+ return ret;
+}
diff --git a/src/parallels/parallels_sdk.h b/src/parallels/parallels_sdk.h
index 3f17fc8..afa6745 100644
--- a/src/parallels/parallels_sdk.h
+++ b/src/parallels/parallels_sdk.h
@@ -64,3 +64,5 @@ int
prlsdkAttachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk);
int
prlsdkDetachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk);
+int
+prlsdkGetBlockStats(virDomainObjPtr dom, virDomainDiskDefPtr disk, virDomainBlockStatsPtr stats);
diff --git a/src/parallels/parallels_utils.c b/src/parallels/parallels_utils.c
index ff9d47d..540986b 100644
--- a/src/parallels/parallels_utils.c
+++ b/src/parallels/parallels_utils.c
@@ -64,6 +64,34 @@ parallelsDomObjFromDomain(virDomainPtr domain)
}
+/**
+ * parallelsDomObjFromDomainRef:
+ * @domain: Domain pointer that has to be looked up
+ *
+ * This function looks up @domain and returns the appropriate virDomainObjPtr
+ * that has to be released by calling virDomainObjEndAPI().
+ *
+ * Returns the domain object with incremented reference counter which is locked
+ * on success, NULL otherwise.
+ */
+virDomainObjPtr
+parallelsDomObjFromDomainRef(virDomainPtr domain)
+{
+ virDomainObjPtr vm;
+ parallelsConnPtr privconn = domain->conn->privateData;
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+ vm = virDomainObjListFindByUUIDRef(privconn->domains, domain->uuid);
+ if (!vm) {
+ virUUIDFormat(domain->uuid, uuidstr);
+ virReportError(VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s' (%s)"),
+ uuidstr, domain->name);
+ return NULL;
+ }
+
+ return vm;
+}
static int
parallelsDoCmdRun(char **outbuf, const char *binary, va_list list)
diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h
index 2d1d405..cdf6082 100644
--- a/src/parallels/parallels_utils.h
+++ b/src/parallels/parallels_utils.h
@@ -73,11 +73,22 @@ struct _parallelsConn {
typedef struct _parallelsConn parallelsConn;
typedef struct _parallelsConn *parallelsConnPtr;
+struct _parallelsContersCache {
+ PRL_HANDLE stats;
+ virCond cond;
+ // -1 - unsubscribed
+ // > -1 - subscribed
+ int count;
+};
+
+typedef struct _parallelsContersCache parallelsContersCache;
+
struct parallelsDomObj {
int id;
char *uuid;
char *home;
PRL_HANDLE sdkdom;
+ parallelsContersCache cache;
};
typedef struct parallelsDomObj *parallelsDomObjPtr;
@@ -91,6 +102,7 @@ int parallelsNetworkClose(virConnectPtr conn);
extern virNetworkDriver parallelsNetworkDriver;
virDomainObjPtr parallelsDomObjFromDomain(virDomainPtr domain);
+virDomainObjPtr parallelsDomObjFromDomainRef(virDomainPtr domain);
virJSONValuePtr parallelsParseOutput(const char *binary, ...)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_SENTINEL;
@@ -106,4 +118,10 @@ virStorageVolPtr parallelsStorageVolLookupByPathLocked(virConnectPtr conn,
int parallelsStorageVolDefRemove(virStoragePoolObjPtr privpool,
virStorageVolDefPtr privvol);
+#define PARALLELS_BLOCK_STATS_FOREACH(OP) \
+ OP(rd_req, VIR_DOMAIN_BLOCK_STATS_READ_REQ, "read_requests") \
+ OP(rd_bytes, VIR_DOMAIN_BLOCK_STATS_READ_BYTES, "read_total") \
+ OP(wr_req, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ, "write_requests") \
+ OP(wr_bytes, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES, "write_total")
+
#endif
--
1.7.1
9 years, 5 months
[libvirt] [PATCH] conf: Fix invalid pointer check in virDomainObjGetDefs
by Peter Krempa
Coverity rightfully determined that in commit 3d021381c71221e563182f03
I made a mistake in the first check if @persDef is not NULL is
dereferencing it rather than checking.
---
Pushed as trivial.
src/conf/domain_conf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 77e198c..68d28f6 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2927,7 +2927,7 @@ virDomainObjGetDefs(virDomainObjPtr vm,
if (liveDef)
*liveDef = NULL;
- if (*persDef)
+ if (persDef)
*persDef = NULL;
if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
--
2.4.1
9 years, 5 months
[libvirt] [PATCH 00/35] vCPU pinning and related refactors - Part 1
by Peter Krempa
These are preliminary refactors that will simplify the code base. The ultimate
goal of this refactoring is to aggregate all vCPU information
(pinning, scheduler,...) into a separate structure rather than storing them in
multiple places. This will then in turn help in making a saner implementation
of the still-planned specific vCPU API.
Peter Krempa (35):
qemu: Fix possible crash in qemuProcessSetVcpuAffinities
conf: Refactor emulatorpin handling
conf: Move pinning information definition closer to the usage place
util: bitmap: Add virBitmapToDataBuf that does not allocate the buffer
qemu: Use virBitmapToDataBuf in qemuDomainGetVcpuPinInfo
qemu: Reuse virBitmapToDataBuf in qemuDomainGetEmulatorPinInfo
qemu: Refactor qemuDomainHelperGetVcpus by reusing virBitmapToDataBuf
libxl: Reuse virBitmapToData in libxlDomainSetVcpuAffinities
libxl: Unbreak vcpu pinning
libxl: Refactor libxlDomainGetVcpuPinInfo
util: Add macro to overflow check integer assignments
monitor: Move documentation for qemuMonitorGetBalloonInfo
qemu: monitor: Make qemuMonitorSetBalloon operate on unsinged long
long
qemu: process: Refactor setup of memory ballooning
qemu: process: Update current balloon state to maximum on vm startup
qemu: Add helper to update domain balloon size and refactor usage
places
qemu: Refactor qemuDomainGetInfo
conf: Store cpu count as unsigned int
lib: virDomainPinIOThread: Remove spurious overflow check
qemu: libxl: vcpupin: Don't reset pinning when pinning to all pcpus
Revert "cputune: Support cputune for xend driver"
libxl: Don't remove vcpu pin definition in libxlDomainCleanup
conf: Add new helpers to resolve virDomainModificationImpact to domain
defs
qemu: Refactor qemuDomainSetMemoryFlags by reusing virDomainObjGetDefs
qemu: Refactor qemuDomainSetMemoryStatsPeriod by reusing
virDomainObjGetDefs
qemu: Refactor qemuDomainGetVcpusFlags by reusing virDomainObjGetDefs
qemu: Refactor qemuDomainGetIOThreadInfo by reusing
virDomainObjGetDefs
qemu: Refactor qemuDomainPinIOThread by reusing virDomainObjGetDefs
qemu: Refactor qemuDomainChgIOThread by reusing virDomainObjGetDefs
qemu: Refactor qemuDomainSetBlkioParameters by reusing
virDomainObjGetDefs
qemu: Refactor qemuDomainPinVcpuFlags by reusing virDomainObjGetDefs
qemu: Refactor qemuDomainGetVcpuPinInfo by reusing virDomainObjGetDefs
qemu: Refactor qemuDomainPinEmulator by reusing virDomainObjGetDefs
qemu: Refactor qemuDomainGetEmulatorPinInfo by reusing
virDomainObjGetDefs
qemu: Refactor qemuDomainSetVcpusFlags by reusing virDomainObjGetDefs
src/conf/domain_conf.c | 229 ++++++++---------
src/conf/domain_conf.h | 78 +++---
src/libvirt-domain.c | 19 --
src/libvirt_private.syms | 5 +-
src/libxl/libxl_domain.c | 44 +---
src/libxl/libxl_driver.c | 57 ++---
src/qemu/qemu_cgroup.c | 2 +-
src/qemu/qemu_domain.c | 64 +++++
src/qemu/qemu_domain.h | 3 +
src/qemu/qemu_driver.c | 593 ++++++++++++-------------------------------
src/qemu/qemu_monitor.c | 12 +-
src/qemu/qemu_monitor.h | 2 +-
src/qemu/qemu_monitor_json.c | 21 +-
src/qemu/qemu_monitor_json.h | 2 +-
src/qemu/qemu_monitor_text.c | 21 +-
src/qemu/qemu_monitor_text.h | 2 +-
src/qemu/qemu_process.c | 47 ++--
src/util/virbitmap.c | 33 ++-
src/util/virbitmap.h | 3 +
src/util/virutil.h | 11 +
src/xen/xend_internal.c | 34 +--
tests/utiltest.c | 30 +++
tools/virsh.pod | 3 +-
23 files changed, 553 insertions(+), 762 deletions(-)
--
2.4.1
9 years, 5 months
[libvirt] [libvirt-php PATCH] docs: remove reference to Red Hat
by Ján Tomko
---
docs/index.html.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/index.html.in b/docs/index.html.in
index da40d7a..bb03d65 100644
--- a/docs/index.html.in
+++ b/docs/index.html.in
@@ -4,7 +4,7 @@
<h1>Libvirt-php</h1>
<p>libvirt-php, originally called php-libvirt, is a project that was started by Radek Hladik in 2010 to integrate libvirt support to PHP.</p>
- <p>In February 2011 the binding has been moved to libvirt.org site and it's currently maintained by Red Hat.</p>
+ <p>In February 2011 the binding was moved to libvirt.org.</p>
<p>
<b>This project is not affiliated with The PHP Group and the PHP project itself.</b>
</p>
--
2.3.6
9 years, 5 months
[libvirt] [PATCH] parallels: simplify event types discrimination
by Nikolay Shirokovskiy
Use issue type instead of event type to group
vm related events. This saves us from
explicit enumeration of all vm even types in
prlsdkHandleVmEvent.
---
src/parallels/parallels_sdk.c | 15 +++++----------
1 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c
index 88ad59b..d5a9790 100644
--- a/src/parallels/parallels_sdk.c
+++ b/src/parallels/parallels_sdk.c
@@ -1681,7 +1681,7 @@ prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque)
parallelsConnPtr privconn = opaque;
PRL_RESULT pret = PRL_ERR_UNINITIALIZED;
PRL_HANDLE_TYPE handleType;
- PRL_EVENT_TYPE prlEventType;
+ PRL_EVENT_ISSUER_TYPE prlIssuerType = PIE_UNKNOWN;
pret = PrlHandle_GetType(prlEvent, &handleType);
prlsdkCheckRetGoto(pret, cleanup);
@@ -1697,20 +1697,15 @@ prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque)
goto cleanup;
}
- PrlEvent_GetType(prlEvent, &prlEventType);
+ PrlEvent_GetIssuerType(prlEvent, &prlIssuerType);
prlsdkCheckRetGoto(pret, cleanup);
- switch (prlEventType) {
- case PET_DSP_EVT_VM_STATE_CHANGED:
- case PET_DSP_EVT_VM_CONFIG_CHANGED:
- case PET_DSP_EVT_VM_CREATED:
- case PET_DSP_EVT_VM_ADDED:
- case PET_DSP_EVT_VM_DELETED:
- case PET_DSP_EVT_VM_UNREGISTERED:
+ switch (prlIssuerType) {
+ case PIE_VIRTUAL_MACHINE:
pret = prlsdkHandleVmEvent(privconn, prlEvent);
break;
default:
- VIR_DEBUG("Skipping event of type %d", prlEventType);
+ VIR_DEBUG("Skipping event of issuer type %d", prlIssuerType);
}
pret = PRL_ERR_SUCCESS;
--
1.7.1
9 years, 5 months
[libvirt] [PATCH] parallels: add block device statistics to driver
by Nikolay Shirokovskiy
Statistics provided through PCS SDK. As we have only async interface in SDK we
need to be subscribed to statistics in order to get it. Trivial solution on
every stat request to subscribe, wait event and then unsubscribe will lead to
significant delays in case of a number of successive requests, as the event
will be delivered on next PCS server notify cycle. On the other hand we don't
want to keep unnesessary subscribtion. So we take an hibrid solution to
subcsribe on first request and then keep a subscription while requests are
active. We populate cache of statistics on subscribtion events and use this
cache to serve libvirts requests.
Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy(a)parallels.com>
---
src/parallels/parallels_driver.c | 106 +++++++++++++++++++++
src/parallels/parallels_sdk.c | 193 ++++++++++++++++++++++++++++++++------
src/parallels/parallels_sdk.h | 2 +
src/parallels/parallels_utils.h | 15 +++
4 files changed, 285 insertions(+), 31 deletions(-)
diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
index 4b87213..ce59e00 100644
--- a/src/parallels/parallels_driver.c
+++ b/src/parallels/parallels_driver.c
@@ -51,6 +51,7 @@
#include "nodeinfo.h"
#include "virstring.h"
#include "cpu/cpu.h"
+#include "virtypedparam.h"
#include "parallels_driver.h"
#include "parallels_utils.h"
@@ -1179,6 +1180,109 @@ parallelsDomainGetMaxMemory(virDomainPtr domain)
return ret;
}
+static int
+parallelsDomainBlockStats(virDomainPtr domain, const char *path,
+ virDomainBlockStatsPtr stats)
+{
+ virDomainObjPtr dom = NULL;
+ int ret = -1;
+ size_t i;
+ int idx;
+
+ if (!(dom = parallelsDomObjFromDomain(domain)))
+ return -1;
+
+ if (*path) {
+ if ((idx = virDomainDiskIndexByName(dom->def, path, false)) < 0) {
+ virReportError(VIR_ERR_INVALID_ARG, _("invalid path: %s"), path);
+ goto cleanup;
+ }
+ if (prlsdkGetBlockStats(dom, dom->def->disks[idx], stats) < 0)
+ goto cleanup;
+ } else {
+ virDomainBlockStatsStruct s;
+
+#define PARALLELS_ZERO_STATS(VAR, TYPE, NAME) \
+ stats->VAR = 0;
+
+ PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_ZERO_STATS)
+
+#undef PARALLELS_ZERO_STATS
+
+ for (i = 0; i < dom->def->ndisks; i++) {
+ if (prlsdkGetBlockStats(dom, dom->def->disks[i], &s) < 0)
+ goto cleanup;
+
+#define PARALLELS_SUM_STATS(VAR, TYPE, NAME) \
+ if (s.VAR != -1) \
+ stats->VAR += s.VAR;
+
+ PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_SUM_STATS)
+
+#undef PARALLELS_SUM_STATS
+ }
+ }
+ stats->errs = -1;
+ ret = 0;
+
+ cleanup:
+ if (dom)
+ virObjectUnlock(dom);
+
+ return ret;
+}
+
+static int
+parallelsDomainBlockStatsFlags(virDomainPtr domain,
+ const char *path,
+ virTypedParameterPtr params,
+ int *nparams,
+ unsigned int flags)
+{
+ virDomainBlockStatsStruct stats;
+ int ret = -1;
+ size_t i;
+
+ virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+ /* We don't return strings, and thus trivially support this flag. */
+ flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
+
+ if (parallelsDomainBlockStats(domain, path, &stats) < 0)
+ goto cleanup;
+
+ if (*nparams == 0) {
+#define PARALLELS_COUNT_STATS(VAR, TYPE, NAME) \
+ if ((stats.VAR) != -1) \
+ ++*nparams;
+
+ PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_COUNT_STATS)
+
+#undef PARALLELS_COUNT_STATS
+ ret = 0;
+ goto cleanup;
+ }
+
+ i = 0;
+#define PARALLELS_BLOCK_STATS_ASSIGN_PARAM(VAR, TYPE, NAME) \
+ if (i < *nparams && (stats.VAR) != -1) { \
+ if (virTypedParameterAssign(params + i, TYPE, \
+ VIR_TYPED_PARAM_LLONG, (stats.VAR)) < 0) \
+ goto cleanup; \
+ i++; \
+ }
+
+ PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_BLOCK_STATS_ASSIGN_PARAM)
+
+#undef PARALLELS_BLOCK_STATS_ASSIGN_PARAM
+
+ *nparams = i;
+ ret = 0;
+
+ cleanup:
+ return ret;
+}
+
+
static virHypervisorDriver parallelsDriver = {
.name = "Parallels",
.connectOpen = parallelsConnectOpen, /* 0.10.0 */
@@ -1228,6 +1332,8 @@ static virHypervisorDriver parallelsDriver = {
.domainManagedSave = parallelsDomainManagedSave, /* 1.2.14 */
.domainManagedSaveRemove = parallelsDomainManagedSaveRemove, /* 1.2.14 */
.domainGetMaxMemory = parallelsDomainGetMaxMemory, /* 1.2.15 */
+ .domainBlockStats = parallelsDomainBlockStats, /* 1.2.16 */
+ .domainBlockStatsFlags = parallelsDomainBlockStatsFlags, /* 1.2.16 */
};
static virConnectDriver parallelsConnectDriver = {
diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c
index 88ad59b..eb8d965 100644
--- a/src/parallels/parallels_sdk.c
+++ b/src/parallels/parallels_sdk.c
@@ -21,6 +21,7 @@
*/
#include <config.h>
+#include <stdarg.h>
#include "virerror.h"
#include "viralloc.h"
@@ -407,6 +408,8 @@ prlsdkDomObjFreePrivate(void *p)
return;
PrlHandle_Free(pdom->sdkdom);
+ PrlHandle_Free(pdom->cache.stats);
+ virCondDestroy(&pdom->cache.cond);
VIR_FREE(pdom->uuid);
VIR_FREE(pdom->home);
VIR_FREE(p);
@@ -1260,6 +1263,13 @@ prlsdkLoadDomain(parallelsConnPtr privconn,
* to NULL temporarily */
pdom->uuid = NULL;
+ pdom->cache.stats = PRL_INVALID_HANDLE;
+ pdom->cache.count = 0;
+ if (virCondInit(&pdom->cache.cond) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot initialize condition"));
+ goto error;
+ }
+
if (prlsdkGetDomainIds(sdkdom, &def->name, def->uuid) < 0)
goto error;
@@ -1636,43 +1646,39 @@ prlsdkHandleVmRemovedEvent(parallelsConnPtr privconn,
}
static PRL_RESULT
-prlsdkHandleVmEvent(parallelsConnPtr privconn, PRL_HANDLE prlEvent)
+prlsdkHandlePerfEvent(parallelsConnPtr privconn,
+ PRL_HANDLE event,
+ unsigned char *uuid)
{
- PRL_RESULT pret;
- char uuidstr[VIR_UUID_STRING_BUFLEN + 2];
- unsigned char uuid[VIR_UUID_BUFLEN];
- PRL_UINT32 bufsize = ARRAY_CARDINALITY(uuidstr);
- PRL_EVENT_TYPE prlEventType;
+ virDomainObjPtr dom = NULL;
+ parallelsDomObjPtr privdom = NULL;
+ PRL_HANDLE job = PRL_INVALID_HANDLE;
- pret = PrlEvent_GetType(prlEvent, &prlEventType);
- prlsdkCheckRetGoto(pret, error);
+ dom = virDomainObjListFindByUUID(privconn->domains, uuid);
+ if (dom == NULL)
+ goto cleanup;
- pret = PrlEvent_GetIssuerId(prlEvent, uuidstr, &bufsize);
- prlsdkCheckRetGoto(pret, error);
+ privdom = dom->privateData;
- if (prlsdkUUIDParse(uuidstr, uuid) < 0)
- return PRL_ERR_FAILURE;
+ PrlHandle_Free(privdom->cache.stats);
+ privdom->cache.stats = event;
+ virCondSignal(&privdom->cache.cond);
- switch (prlEventType) {
- case PET_DSP_EVT_VM_STATE_CHANGED:
- return prlsdkHandleVmStateEvent(privconn, prlEvent, uuid);
- case PET_DSP_EVT_VM_CONFIG_CHANGED:
- return prlsdkHandleVmConfigEvent(privconn, uuid);
- case PET_DSP_EVT_VM_CREATED:
- case PET_DSP_EVT_VM_ADDED:
- return prlsdkHandleVmAddedEvent(privconn, uuid);
- case PET_DSP_EVT_VM_DELETED:
- case PET_DSP_EVT_VM_UNREGISTERED:
- return prlsdkHandleVmRemovedEvent(privconn, uuid);
- break;
- default:
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Can't handle event of type %d"), prlEventType);
- return PRL_ERR_FAILURE;
+ ++privdom->cache.count;
+
+ if (privdom->cache.count > 3) {
+ job = PrlVm_UnsubscribeFromPerfStats(privdom->sdkdom);
+ if (PRL_FAILED(waitJob(job)))
+ goto cleanup;
+ privdom->cache.count = 0;
+ privdom->cache.stats = PRL_INVALID_HANDLE;
}
- error:
- return PRL_ERR_FAILURE;
+ cleanup:
+ if (dom)
+ virObjectUnlock(dom);
+
+ return PRL_ERR_SUCCESS;
}
static PRL_RESULT
@@ -1682,6 +1688,9 @@ prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque)
PRL_RESULT pret = PRL_ERR_UNINITIALIZED;
PRL_HANDLE_TYPE handleType;
PRL_EVENT_TYPE prlEventType;
+ char uuidstr[VIR_UUID_STRING_BUFLEN + 2];
+ unsigned char uuid[VIR_UUID_BUFLEN];
+ PRL_UINT32 bufsize = ARRAY_CARDINALITY(uuidstr);
pret = PrlHandle_GetType(prlEvent, &handleType);
prlsdkCheckRetGoto(pret, cleanup);
@@ -1700,14 +1709,31 @@ prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque)
PrlEvent_GetType(prlEvent, &prlEventType);
prlsdkCheckRetGoto(pret, cleanup);
+ pret = PrlEvent_GetIssuerId(prlEvent, uuidstr, &bufsize);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ if (prlsdkUUIDParse(uuidstr, uuid) < 0)
+ goto cleanup;
+
switch (prlEventType) {
case PET_DSP_EVT_VM_STATE_CHANGED:
+ prlsdkHandleVmStateEvent(privconn, prlEvent, uuid);
+ break;
case PET_DSP_EVT_VM_CONFIG_CHANGED:
+ prlsdkHandleVmConfigEvent(privconn, uuid);
+ break;
case PET_DSP_EVT_VM_CREATED:
case PET_DSP_EVT_VM_ADDED:
+ prlsdkHandleVmAddedEvent(privconn, uuid);
+ break;
case PET_DSP_EVT_VM_DELETED:
case PET_DSP_EVT_VM_UNREGISTERED:
- pret = prlsdkHandleVmEvent(privconn, prlEvent);
+ prlsdkHandleVmRemovedEvent(privconn, uuid);
+ break;
+ case PET_DSP_EVT_VM_PERFSTATS:
+ prlsdkHandlePerfEvent(privconn, prlEvent, uuid);
+ // above function takes own of event
+ prlEvent = PRL_INVALID_HANDLE;
break;
default:
VIR_DEBUG("Skipping event of type %d", prlEventType);
@@ -3455,3 +3481,108 @@ prlsdkDomainManagedSaveRemove(virDomainObjPtr dom)
return 0;
}
+
+static int
+prlsdkExtractStatsParam(PRL_HANDLE sdkstats, const char *name, long long *val)
+{
+ PRL_HANDLE param = PRL_INVALID_HANDLE;
+ PRL_RESULT pret;
+ PRL_INT64 pval = 0;
+ int ret = -1;
+
+ pret = PrlEvent_GetParamByName(sdkstats, name, ¶m);
+ if (pret == PRL_ERR_NO_DATA) {
+ *val = -1;
+ ret = 0;
+ goto cleanup;
+ } else if (PRL_FAILED(pret)) {
+ logPrlError(pret);
+ goto cleanup;
+ }
+ pret = PrlEvtPrm_ToInt64(param, &pval);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ *val = pval;
+ ret = 0;
+
+ cleanup:
+ PrlHandle_Free(param);
+ return ret;
+}
+
+static int
+prlsdkGetStatsParam(virDomainObjPtr dom, const char *name, long long *val)
+{
+ parallelsDomObjPtr privdom = dom->privateData;
+ PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+ if (privdom->cache.stats != PRL_INVALID_HANDLE) {
+ privdom->cache.count = 0;
+ return prlsdkExtractStatsParam(privdom->cache.stats, name, val);
+ }
+
+ job = PrlVm_SubscribeToPerfStats(privdom->sdkdom, NULL);
+ if (PRL_FAILED(waitJob(job)))
+ goto error;
+
+ while (privdom->cache.stats == PRL_INVALID_HANDLE) {
+ if (virCondWait(&privdom->cache.cond, &dom->parent.lock) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to wait on monitor condition"));
+ goto error;
+ }
+ }
+
+ return prlsdkExtractStatsParam(privdom->cache.stats, name, val);
+ error:
+ return -1;
+}
+
+int
+prlsdkGetBlockStats(virDomainObjPtr dom, virDomainDiskDefPtr disk, virDomainBlockStatsPtr stats)
+{
+ virDomainDeviceDriveAddressPtr address;
+ int idx;
+ const char *prefix;
+ int ret = -1;
+ char *name = NULL;
+
+ address = &disk->info.addr.drive;
+ switch (disk->bus) {
+ case VIR_DOMAIN_DISK_BUS_IDE:
+ prefix = "ide";
+ idx = address->bus * 2 + address->unit;
+ break;
+ case VIR_DOMAIN_DISK_BUS_SATA:
+ prefix = "sata";
+ idx = address->unit;
+ break;
+ case VIR_DOMAIN_DISK_BUS_SCSI:
+ prefix = "scsi";
+ idx = address->unit;
+ break;
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unknown disk bus: %X"), disk->bus);
+ goto cleanup;
+ }
+
+
+#define PRLSDK_GET_STAT_PARAM(VAL, TYPE, NAME) \
+ if (virAsprintf(&name, "devices.%s%d.%s", prefix, idx, NAME) < 0) \
+ goto cleanup; \
+ if (prlsdkGetStatsParam(dom, name, &stats->VAL) < 0) \
+ goto cleanup; \
+ VIR_FREE(name);
+
+ PARALLELS_BLOCK_STATS_FOREACH(PRLSDK_GET_STAT_PARAM)
+
+#undef PRLSDK_GET_STAT_PARAM
+
+ ret = 0;
+
+ cleanup:
+
+ VIR_FREE(name);
+ return ret;
+}
diff --git a/src/parallels/parallels_sdk.h b/src/parallels/parallels_sdk.h
index 3f17fc8..afa6745 100644
--- a/src/parallels/parallels_sdk.h
+++ b/src/parallels/parallels_sdk.h
@@ -64,3 +64,5 @@ int
prlsdkAttachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk);
int
prlsdkDetachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk);
+int
+prlsdkGetBlockStats(virDomainObjPtr dom, virDomainDiskDefPtr disk, virDomainBlockStatsPtr stats);
diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h
index 2d1d405..e424405 100644
--- a/src/parallels/parallels_utils.h
+++ b/src/parallels/parallels_utils.h
@@ -73,11 +73,20 @@ struct _parallelsConn {
typedef struct _parallelsConn parallelsConn;
typedef struct _parallelsConn *parallelsConnPtr;
+struct _parallelsContersCache {
+ PRL_HANDLE stats;
+ virCond cond;
+ int count;
+};
+
+typedef struct _parallelsContersCache parallelsContersCache;
+
struct parallelsDomObj {
int id;
char *uuid;
char *home;
PRL_HANDLE sdkdom;
+ parallelsContersCache cache;
};
typedef struct parallelsDomObj *parallelsDomObjPtr;
@@ -106,4 +115,10 @@ virStorageVolPtr parallelsStorageVolLookupByPathLocked(virConnectPtr conn,
int parallelsStorageVolDefRemove(virStoragePoolObjPtr privpool,
virStorageVolDefPtr privvol);
+#define PARALLELS_BLOCK_STATS_FOREACH(OP) \
+ OP(rd_req, VIR_DOMAIN_BLOCK_STATS_READ_REQ, "read_requests") \
+ OP(rd_bytes, VIR_DOMAIN_BLOCK_STATS_READ_BYTES, "read_total") \
+ OP(wr_req, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ, "write_requests") \
+ OP(wr_bytes, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES, "write_total")
+
#endif
--
1.7.1
9 years, 5 months
[libvirt] [PATCH] qemu: Check for qemu capability when calling virDomainGetBlockIoTune()
by Martin Kletzander
When getting block device I/O tuning data there is no check for whether
QEMU supports such options and the call fails on
qemuMonitorGetBlockIoThrottle() when getting the particular throttle
data. So try reporting a better error when blkdeviotune is not
supported.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1224053
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
src/qemu/qemu_driver.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index d1b00a2014ba..8f8ad8ba5bf5 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -18065,6 +18065,12 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
* because we need vm->privateData which need
* virDomainLiveConfigHelperMethod to do so. */
priv = vm->privateData;
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE)) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("block I/O throttling not supported with this "
+ "QEMU binary"));
+ goto endjob;
+ }
supportMaxOptions = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX);
}
--
2.4.2
9 years, 5 months
[libvirt] [PATCH] docs: php: remove reference to Red Hat
by Ján Tomko
Also remove the redudant apostrophe from "it's".
---
docs/php.html.in | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/docs/php.html.in b/docs/php.html.in
index d9a3c1b..c10b0aa 100644
--- a/docs/php.html.in
+++ b/docs/php.html.in
@@ -6,8 +6,7 @@
<h2>Presentation</h2>
<p>The libvirt-php, originally called php-libvirt, is the PHP API bindings for
- the libvirt virtualization toolkit originally developed by Radek Hladik but
- currently maintained by Red Hat.</p>
+ the libvirt virtualization toolkit originally developed by Radek Hladik.</p>
<h2>Getting the source</h2>
<p> The PHP bindings code source is now maintained in a <a
@@ -26,7 +25,7 @@ It can also be browsed at
<p></p>
<h2>Project pages</h2>
-<p>Since February 2011 the project have it's own pages hosted at libvirt.org. For more information on the project
+<p>Since February 2011 the project has its own pages hosted at libvirt.org. For more information on the project
please refer to <a href="http://libvirt.org/php">http://libvirt.org/php</a>.
</p>
--
2.3.6
9 years, 5 months
[libvirt] [PATCH] maint: remove redundant apostrophes from 'its'
by Ján Tomko
---
docs/formatnode.html.in | 2 +-
src/conf/storage_conf.c | 2 +-
src/esx/esx_driver.c | 2 +-
src/esx/esx_network_driver.c | 2 +-
src/esx/esx_storage_backend_iscsi.c | 2 +-
src/esx/esx_storage_backend_vmfs.c | 2 +-
src/libxl/libxl_domain.c | 2 +-
src/network/bridge_driver.c | 2 +-
src/parallels/parallels_storage.c | 2 +-
src/qemu/qemu_driver.c | 4 ++--
src/qemu/qemu_migration.c | 2 +-
src/vbox/vbox_common.c | 2 +-
12 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/docs/formatnode.html.in b/docs/formatnode.html.in
index ba9a0f8..3ff1bef 100644
--- a/docs/formatnode.html.in
+++ b/docs/formatnode.html.in
@@ -122,7 +122,7 @@
This optional element contains information on PCI Express part of
the device. For example, it can contain a child element
<code>link</code> which addresses the PCI Express device's link.
- While a device has it's own capabilities
+ While a device has its own capabilities
(<code>validity='cap'</code>), the actual run time capabilities
are negotiated on the device initialization
(<code>validity='sta'</code>). The <code>link</code> element then
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index df536d4..4bbed4f 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -2335,7 +2335,7 @@ matchFCHostToSCSIHost(virConnectPtr conn,
char *parent_name = NULL;
unsigned int fc_hostnum;
- /* If we have a parent defined, get it's hostnum, and compare to the
+ /* If we have a parent defined, get its hostnum, and compare to the
* scsi_hostnum. If they are the same, then we have a match
*/
if (fc_adapter.data.fchost.parent &&
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index bf51213..c304ff3 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -267,7 +267,7 @@ esxParseVMXFileName(const char *fileName, void *opaque)
* in the documentation of esxParseVMXFileName.
*
* Firstly parse the datastore path. Then use the datastore name to lookup the
- * datastore and it's mount path. Finally concatenate the mount path, directory
+ * datastore and its mount path. Finally concatenate the mount path, directory
* and file name to an absolute path and return it. Detect the separator type
* based on the mount path.
*/
diff --git a/src/esx/esx_network_driver.c b/src/esx/esx_network_driver.c
index 6793b80..b19c06a 100644
--- a/src/esx/esx_network_driver.c
+++ b/src/esx/esx_network_driver.c
@@ -38,7 +38,7 @@
#define VIR_FROM_THIS VIR_FROM_ESX
/*
- * The UUID of a network is the MD5 sum of it's key. Therefore, verify that
+ * The UUID of a network is the MD5 sum of its key. Therefore, verify that
* UUID and MD5 sum match in size, because we rely on that.
*/
verify(MD5_DIGEST_SIZE == VIR_UUID_BUFLEN);
diff --git a/src/esx/esx_storage_backend_iscsi.c b/src/esx/esx_storage_backend_iscsi.c
index e4d2692..a9a19cf 100644
--- a/src/esx/esx_storage_backend_iscsi.c
+++ b/src/esx/esx_storage_backend_iscsi.c
@@ -42,7 +42,7 @@
#define VIR_FROM_THIS VIR_FROM_ESX
/*
- * The UUID of a storage pool is the MD5 sum of it's mount path. Therefore,
+ * The UUID of a storage pool is the MD5 sum of its mount path. Therefore,
* verify that UUID and MD5 sum match in size, because we rely on that.
*/
verify(MD5_DIGEST_SIZE == VIR_UUID_BUFLEN);
diff --git a/src/esx/esx_storage_backend_vmfs.c b/src/esx/esx_storage_backend_vmfs.c
index 0dcf419..d03d33a 100644
--- a/src/esx/esx_storage_backend_vmfs.c
+++ b/src/esx/esx_storage_backend_vmfs.c
@@ -48,7 +48,7 @@
VIR_LOG_INIT("esx.esx_storage_backend_vmfs");
/*
- * The UUID of a storage pool is the MD5 sum of it's mount path. Therefore,
+ * The UUID of a storage pool is the MD5 sum of its mount path. Therefore,
* verify that UUID and MD5 sum match in size, because we rely on that.
*/
verify(MD5_DIGEST_SIZE == VIR_UUID_BUFLEN);
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index f339d9c..d925917 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -518,7 +518,7 @@ libxlDomainEventHandler(void *data, VIR_LIBXL_EVENT_CONST libxl_event *event)
/*
* Similar to the xl implementation, ignore SUSPEND. Any actions needed
- * after calling libxl_domain_suspend() are handled by it's callers.
+ * after calling libxl_domain_suspend() are handled by its callers.
*/
if (xl_reason == LIBXL_SHUTDOWN_REASON_SUSPEND)
goto error;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 72be51e..3d6721b 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1601,7 +1601,7 @@ networkRadvdConfContents(virNetworkObjPtr network, char **configstr)
return ret;
}
-/* write file and return it's name (which must be freed by caller) */
+/* write file and return its name (which must be freed by caller) */
static int
networkRadvdConfWrite(virNetworkDriverStatePtr driver,
virNetworkObjPtr network,
diff --git a/src/parallels/parallels_storage.c b/src/parallels/parallels_storage.c
index 3dcc44d..ff3d0fa 100644
--- a/src/parallels/parallels_storage.c
+++ b/src/parallels/parallels_storage.c
@@ -212,7 +212,7 @@ parallelsPoolCreateByPath(virConnectPtr conn, const char *path)
/*
* Create pool of type VIR_STORAGE_POOL_DIR with
- * path to the VM, if it's not exists.
+ * path to the VM, if it does not exist.
*/
static virStoragePoolObjPtr
parallelsPoolAddByDomain(virConnectPtr conn, virDomainObjPtr dom)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 63001b1..84e0568 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2959,7 +2959,7 @@ qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid,
is_reg = !!S_ISREG(sb.st_mode);
/* If the path is regular file which exists
* already and dynamic_ownership is off, we don't
- * want to change it's ownership, just open it as-is */
+ * want to change its ownership, just open it as-is */
if (is_reg && !dynamicOwnership) {
uid = sb.st_uid;
gid = sb.st_gid;
@@ -16396,7 +16396,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
* XXX On libvirtd restarts, if we missed the qemu event, we need
* to double check what state qemu is in.
* XXX We should be using qemu's rerror flag to make sure the job
- * remains alive until we know it's final state.
+ * remains alive until we know its final state.
* XXX If the abort command is synchronous but the qemu event says
* that pivot failed, we need to reflect that failure into the
* overall return value. */
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index f7432e8..70400f3 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -125,7 +125,7 @@ struct _qemuMigrationCookieNetData {
int vporttype; /* enum virNetDevVPortProfile */
/*
- * Array of pointers to saved data. Each VIF will have it's own
+ * Array of pointers to saved data. Each VIF will have its own
* data to transfer.
*/
char *portdata;
diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c
index ba0b039..813a171 100644
--- a/src/vbox/vbox_common.c
+++ b/src/vbox/vbox_common.c
@@ -4603,7 +4603,7 @@ vboxSnapshotRedefine(virDomainPtr dom,
readWriteDisk->location = realReadWriteDisksPath[it];
/*
* We get the current snapshot's read-only disk uuid in order to add the
- * read-write disk to the media registry as it's child. The read-only disk
+ * read-write disk to the media registry as its child. The read-only disk
* is already in the media registry because it is the fake disk's parent.
*/
parentUuid = virVBoxSnapshotConfHardDiskUuidByLocation(snapshotMachineDesc,
--
2.3.6
9 years, 5 months
[libvirt] [v2] storage-pool: API to get/set autostart flag
by Zeeshan Ali (Khattak)
Add binding for virStoragePoolGetAutostart & virStoragePoolSetAutostart.
---
libvirt-gobject/libvirt-gobject-storage-pool.c | 51 ++++++++++++++++++++++++++
libvirt-gobject/libvirt-gobject-storage-pool.h | 5 +++
libvirt-gobject/libvirt-gobject.sym | 6 +++
3 files changed, 62 insertions(+)
diff --git a/libvirt-gobject/libvirt-gobject-storage-pool.c b/libvirt-gobject/libvirt-gobject-storage-pool.c
index f3eac0d..7f26b1b 100644
--- a/libvirt-gobject/libvirt-gobject-storage-pool.c
+++ b/libvirt-gobject/libvirt-gobject-storage-pool.c
@@ -1048,6 +1048,57 @@ gboolean gvir_storage_pool_delete (GVirStoragePool *pool,
return TRUE;
}
+/**
+ * gvir_storage_pool_get_autostart:
+ * @pool: the storage pool
+ * @err: return location for any #GError
+ *
+ * Return value: #True if autostart is enabled, #False otherwise.
+ */
+gboolean gvir_storage_pool_get_autostart(GVirStoragePool *pool,
+ GError **err)
+{
+ int ret;
+
+ g_return_val_if_fail(GVIR_IS_STORAGE_POOL(pool), FALSE);
+ g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
+
+ if (virStoragePoolGetAutostart(pool->priv->handle, &ret)) {
+ gvir_set_error_literal(err, GVIR_STORAGE_POOL_ERROR,
+ 0,
+ "Failed to get autostart flag from storage pool");
+ }
+
+ return !!ret;
+}
+
+/**
+ * gvir_storage_pool_set_autostart:
+ * @pool: the storage pool
+ * @autostart: Whether or not to autostart
+ * @err: return location for any #GError
+ *
+ * Sets whether or not storage pool @pool is started automatically on boot.
+ *
+ * Return value: #TRUE on success, #FALSE otherwise.
+ */
+gboolean gvir_storage_pool_set_autostart(GVirStoragePool *pool,
+ gboolean autostart,
+ GError **err)
+{
+ g_return_val_if_fail(GVIR_IS_STORAGE_POOL(pool), FALSE);
+ g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
+
+ if (virStoragePoolSetAutostart(pool->priv->handle, autostart)) {
+ gvir_set_error_literal(err, GVIR_STORAGE_POOL_ERROR,
+ 0,
+ "Failed to set autostart flag on storage pool");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static void
gvir_storage_pool_delete_helper(GSimpleAsyncResult *res,
GObject *object,
diff --git a/libvirt-gobject/libvirt-gobject-storage-pool.h b/libvirt-gobject/libvirt-gobject-storage-pool.h
index f8529f0..f7f879c 100644
--- a/libvirt-gobject/libvirt-gobject-storage-pool.h
+++ b/libvirt-gobject/libvirt-gobject-storage-pool.h
@@ -166,6 +166,11 @@ void gvir_storage_pool_delete_async (GVirStoragePool *pool,
gboolean gvir_storage_pool_delete_finish(GVirStoragePool *pool,
GAsyncResult *result,
GError **err);
+gboolean gvir_storage_pool_get_autostart(GVirStoragePool *pool,
+ GError **err);
+gboolean gvir_storage_pool_set_autostart(GVirStoragePool *pool,
+ gboolean autostart,
+ GError **err);
G_END_DECLS
diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym
index 927cad9..dcda675 100644
--- a/libvirt-gobject/libvirt-gobject.sym
+++ b/libvirt-gobject/libvirt-gobject.sym
@@ -265,4 +265,10 @@ LIBVIRT_GOBJECT_0.2.0 {
gvir_domain_open_graphics_fd;
} LIBVIRT_GOBJECT_0.1.9;
+LIBVIRT_GOBJECT_0.2.1 {
+ global:
+ gvir_storage_pool_get_autostart;
+ gvir_storage_pool_set_autostart;
+} LIBVIRT_GOBJECT_0.2.0;
+
# .... define new API here using predicted next version number ....
--
2.4.2
9 years, 5 months