[libvirt] computing the correct rom for seabios to recognize SR-IOV
by Ido Barkan
Hi,
I am a VDSM developer at Ovirt.
Recently, we opened Bug 1224954 - seabios does not recognize a direct attached nic [1]
and discovered that in order to leverage the <rom bar='on' file=FILE/>
(as explained in [2]) in the hostdev element, one must compute the correct FILE
path by following something similar to:
$ lspci -v #loof for the VF nic part
00:08.0 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
$ grep "82576 Virtual Function" /usr/share/hwdata/pci.ids
10ca 82576 Virtual Function
$ rpm -ql ipxe-roms | grep 10ca
/usr/share/ipxe/808610ca.rom
This computation must be implemented for Ovirt to support booting a VM from PXE using a SRIOV VF.
Is there any chance that this computation will be done automatically by libvirt?
Thanks,
Ido
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1224954
[2] https://libvirt.org/formatdomain.html#elementsHostDevSubsys
9 years, 5 months
[libvirt] [PATCH] logical: Fix typo in error message
by John Ferlan
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
Pushing under the trivial rule
src/storage/storage_backend_logical.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/storage/storage_backend_logical.c b/src/storage/storage_backend_logical.c
index 9c77b4c..070f2bd 100644
--- a/src/storage/storage_backend_logical.c
+++ b/src/storage/storage_backend_logical.c
@@ -862,7 +862,8 @@ virStorageBackendLogicalVolWipe(virConnectPtr conn,
* unsupported.
*/
virReportError(VIR_ERR_NO_SUPPORT,
- _("logical volue '%s' is sparse, volume wipe not supported"),
+ _("logical volume '%s' is sparse, volume wipe "
+ "not supported"),
vol->target.path);
return -1;
}
--
2.1.0
9 years, 5 months
[libvirt] [PATCH 0/2] Fix network names with quotes
by Shivaprasad G Bhat
The following series implements...
---
Shivaprasad G Bhat (2):
fix domaincommon.rng to accept network name with quotes
escape quotes for dsmasq conf contents
docs/schemas/domaincommon.rng | 2 +-
src/util/virdnsmasq.c | 25 +++++++++++++++----
src/util/virpidfile.c | 15 ++++++++----
.../nat-network-name-with-quotes.conf | 20 +++++++++++++++
.../nat-network-name-with-quotes.xml | 26 ++++++++++++++++++++
tests/networkxml2conftest.c | 1 +
6 files changed, 79 insertions(+), 10 deletions(-)
create mode 100644 tests/networkxml2confdata/nat-network-name-with-quotes.conf
create mode 100644 tests/networkxml2confdata/nat-network-name-with-quotes.xml
--
Signature
9 years, 5 months
[libvirt] [PATCH] storage: Need to set secrettype for direct iscsi disk volume
by John Ferlan
https://bugzilla.redhat.com/show_bug.cgi?id=1200206
Commit id '1b4eaa61' added the ability to have a mode='direct' for
an iscsi disk volume. It relied on virStorageTranslateDiskSourcePool
in order to copy any disk source pool authentication information to
the direct disk volume, but it neglected to also copy the 'secrettype'
field which ends up being used in the domain volume formatting code.
Adding a secrettype for this case will allow for proper formatting later
and allow disk snapshotting to work properly
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/storage/storage_driver.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index ab8675d..57060ab 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -3310,6 +3310,16 @@ virStorageTranslateDiskSourcePool(virConnectPtr conn,
&pooldef->source) < 0)
goto cleanup;
+ /* Source pool may not fill in the secrettype field,
+ * so we need to do so here
+ */
+ if (def->src->auth && !def->src->auth->secrettype) {
+ const char *secrettype =
+ virSecretUsageTypeToString(VIR_SECRET_USAGE_TYPE_ISCSI);
+ if (VIR_STRDUP(def->src->auth->secrettype, secrettype) < 0)
+ goto cleanup;
+ }
+
if (virStorageAddISCSIPoolSourceHost(def, pooldef) < 0)
goto cleanup;
break;
--
2.1.0
9 years, 5 months
[libvirt] [PATCH 0/4 v2] parallels: better support of volume based disks in containers
by Maxim Nestratov
v1-v2 change:
* Single patch was split into smaller pieces
* Corrected conflict of "/" mount point in case both filesystem
and block device disks are being added.
It is possible to attach volumes to containers but since they are
added they are reported erroneously as filesystems. This is fixed
in this patch set. As soon as bus type has no meaning for containers
we always report SATA for such disks.
In case a container is created with a disk based on physical
volume and there is no filesystem disk with root mount point we are
expected to specify mount point block device based disk to be able to
boot from it.
Maxim Nestratov (4):
parallels: add isCt parameter to prlsdkGetDiskInfo and prlsdkAddDisk
parallels: process '/' mount point correctly for containers
parallels: report SATA bus type for container block devices disks
parallels: treat block devices as disks for containers
src/parallels/parallels_sdk.c | 52 +++++++++++++++++++++++++++++++------------
1 file changed, 38 insertions(+), 14 deletions(-)
--
2.1.0
9 years, 5 months
Re: [libvirt] [libvirt-php] [PATCH v1] update snapshot api
by Vasiliy Tolstov
2015-05-07 17:21 GMT+03:00 Vasiliy Tolstov <v.tolstov(a)selfip.ru>:
> * add constants from libvirt to snapshots api
> * add flags to snapshot functions
This is for php libvirt binding
--
Vasiliy Tolstov,
e-mail: v.tolstov(a)selfip.ru
jabber: vase(a)selfip.ru
9 years, 5 months
[libvirt] Build failed in Jenkins: libvirt-syntax-check #3577
by Jenkins CI
See <http://honk.sigxcpu.org:8001/job/libvirt-syntax-check/3577/>
------------------------------------------
Started by upstream project "libvirt-build" build number 4064
Started by upstream project "libvirt-build" build number 4065
Building on master in workspace <http://honk.sigxcpu.org:8001/job/libvirt-syntax-check/ws/>
[workspace] $ /bin/sh -xe /tmp/hudson282348035376735129.sh
+ make syntax-check
GEN bracket-spacing-check
GFDL_version
0.73 GFDL_version
TAB_in_indentation
0.54 TAB_in_indentation
Wundef_boolean
0.31 Wundef_boolean
avoid_attribute_unused_in_header
0.39 avoid_attribute_unused_in_header
avoid_ctype_macros
1.01 avoid_ctype_macros
avoid_if_before_free
7.25 avoid_if_before_free
avoid_strcase
0.84 avoid_strcase
avoid_write
0.42 avoid_write
bindtextdomain
0.39 bindtextdomain
cast_of_argument_to_free
0.68 cast_of_argument_to_free
cast_of_x_alloc_return_value
0.74 cast_of_x_alloc_return_value
changelog
0.31 changelog
const_long_option
0.77 const_long_option
copyright_check
1.08 copyright_check
copyright_format
2.18 copyright_format
copyright_usage
2.05 copyright_usage
correct_id_types
0.84 correct_id_types
curly_braces_style
1.51 curly_braces_style
error_message_period
0.67 error_message_period
error_message_warn_fatal
0.61 error_message_warn_fatal
flags_debug
1.64 flags_debug
flags_usage
1.38 flags_usage
forbid_const_pointer_typedef
1.51 forbid_const_pointer_typedef
forbid_manual_xml_indent
0.75 forbid_manual_xml_indent
libvirt_unmarked_diagnostics
2.20 libvirt_unmarked_diagnostics
m4_quote_check
0.42 m4_quote_check
makefile_TAB_only_indentation
0.46 makefile_TAB_only_indentation
makefile_at_at_check
0.56 makefile_at_at_check
makefile_conditionals
0.47 makefile_conditionals
po_check
15.54 po_check
preprocessor_indentation
cppi: src/parallels/parallels_driver.c: line 1255: not properly formatted;
there must be exactly one SPACE character after each
#if, #elif, and #define directive
cppi: src/parallels/parallels_utils.h: line 122: not properly indented
maint.mk: incorrect preprocessor indentation
make: *** [sc_preprocessor_indentation] Error 1
Build step 'Execute shell' marked build as failure
9 years, 5 months
[libvirt] [PATCH] parallels: fix formatting errors in parallels driver
by Dmitry Guryanov
This patch fixes several formatting errors, which I
missed before pushing previous patches. Mostly because
of missing cppi package.
Signed-off-by: Dmitry Guryanov <dguryanov(a)parallels.com>
---
src/parallels/parallels_driver.c | 8 ++++----
src/parallels/parallels_sdk.c | 4 ++--
src/parallels/parallels_utils.h | 10 +++++-----
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
index fdba0db..706229d 100644
--- a/src/parallels/parallels_driver.c
+++ b/src/parallels/parallels_driver.c
@@ -1252,13 +1252,13 @@ parallelsDomainBlockStats(virDomainPtr domain, const char *path,
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;
+#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
+#undef PARALLELS_SUM_STATS
}
}
stats->errs = -1;
diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c
index 4d5099c..104c905 100644
--- a/src/parallels/parallels_sdk.c
+++ b/src/parallels/parallels_sdk.c
@@ -501,9 +501,9 @@ prlsdkGetDiskInfo(PRL_HANDLE prldisk,
goto cleanup;
/* Let physical devices added to CT look like SATA disks */
- if (isCt)
+ if (isCt) {
ifType = PMS_SATA_DEVICE;
- else {
+ } else {
pret = PrlVmDev_GetIfaceType(prldisk, &ifType);
prlsdkCheckRetGoto(pret, cleanup);
}
diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h
index 84bef24..5db65bd 100644
--- a/src/parallels/parallels_utils.h
+++ b/src/parallels/parallels_utils.h
@@ -119,10 +119,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")
+# 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
--
2.1.0
9 years, 5 months
[libvirt] [PATCH v5] 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 PARALLELS_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 | 200 +++++++++++++++++++++++++++++++++++++-
src/parallels/parallels_sdk.h | 2 +
src/parallels/parallels_utils.c | 28 ++++++
src/parallels/parallels_utils.h | 18 ++++
5 files changed, 350 insertions(+), 4 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 6d63759..00e51f4 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;
@@ -1611,6 +1622,51 @@ prlsdkHandleVmRemovedEvent(parallelsConnPtr privconn,
return;
}
+#define PARALLELS_STATISTICS_DROP_COUNT 3
+
+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 > PARALLELS_STATISTICS_DROP_COUNT) {
+ 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 void
prlsdkHandleVmEvent(parallelsConnPtr privconn, PRL_HANDLE prlEvent)
{
@@ -1621,13 +1677,13 @@ prlsdkHandleVmEvent(parallelsConnPtr privconn, PRL_HANDLE prlEvent)
PRL_EVENT_TYPE prlEventType;
pret = PrlEvent_GetType(prlEvent, &prlEventType);
- prlsdkCheckRetGoto(pret, error);
+ prlsdkCheckRetGoto(pret, cleanup);
pret = PrlEvent_GetIssuerId(prlEvent, uuidstr, &bufsize);
- prlsdkCheckRetGoto(pret, error);
+ prlsdkCheckRetGoto(pret, cleanup);
if (prlsdkUUIDParse(uuidstr, uuid) < 0)
- return;
+ goto cleanup;
switch (prlEventType) {
case PET_DSP_EVT_VM_STATE_CHANGED:
@@ -1644,12 +1700,18 @@ prlsdkHandleVmEvent(parallelsConnPtr privconn, PRL_HANDLE prlEvent)
case PET_DSP_EVT_VM_UNREGISTERED:
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);
}
- error:
+ cleanup:
+ PrlHandle_Free(prlEvent);
return;
}
@@ -1677,6 +1739,8 @@ prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque)
switch (prlIssuerType) {
case PIE_VIRTUAL_MACHINE:
prlsdkHandleVmEvent(privconn, prlEvent);
+ // above function takes own of event
+ prlEvent = PRL_INVALID_HANDLE;
break;
default:
VIR_DEBUG("Skipping event of issuer type %d", prlIssuerType);
@@ -1687,6 +1751,7 @@ prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque)
return PRL_ERR_SUCCESS;
}
+
int prlsdkSubscribeToPCSEvents(parallelsConnPtr privconn)
{
PRL_RESULT pret = PRL_ERR_UNINITIALIZED;
@@ -3423,3 +3488,130 @@ 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);
+ }
+
+ if (privdom->cache.count == -1) {
+ job = PrlVm_SubscribeToPerfStats(privdom->sdkdom, NULL);
+ if (PRL_FAILED(waitJob(job)))
+ goto error;
+ }
+
+ // change state to subscribed in case of unsubscribed
+ // or reset count so we stop unsubscribe attempts
+ 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..6268882 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 _parallelsCountersCache {
+ PRL_HANDLE stats;
+ virCond cond;
+ // -1 - unsubscribed
+ // > -1 - subscribed
+ int count;
+};
+
+typedef struct _parallelsCountersCache parallelsCountersCache;
+
struct parallelsDomObj {
int id;
char *uuid;
char *home;
PRL_HANDLE sdkdom;
+ parallelsCountersCache 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] virsh: change-media: Fix behavior with --update without a source
by Peter Krempa
Docs state that it should behave like eject. Currently the code does not
do that. This is a regression since f4b5f53027da4fed2250628e11bac4019.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1229592
---
tools/virsh-domain.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index a25b7ba..4c47473 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -12411,6 +12411,15 @@ cmdChangeMedia(vshControl *ctl, const vshCmd *cmd)
VSH_EXCLUSIVE_OPTIONS_VAR(eject, block);
+ if (vshCommandOptStringReq(ctl, cmd, "source", &source) < 0)
+ return false;
+
+ /* Docs state that update without source is eject */
+ if (update && !source) {
+ update = false;
+ eject = true;
+ }
+
if (eject) {
update_type = VSH_UPDATE_DISK_XML_EJECT;
action = "eject";
@@ -12445,9 +12454,6 @@ cmdChangeMedia(vshControl *ctl, const vshCmd *cmd)
if (vshCommandOptStringReq(ctl, cmd, "path", &path) < 0)
goto cleanup;
- if (vshCommandOptStringReq(ctl, cmd, "source", &source) < 0)
- goto cleanup;
-
if (flags & VIR_DOMAIN_AFFECT_CONFIG)
doc = virDomainGetXMLDesc(dom, VIR_DOMAIN_XML_INACTIVE);
else
--
2.4.1
9 years, 5 months