[libvirt] [RFC] Memory controller exploitation in libvirt
by Nikunj A. Dadhania
Subject: [RFC] Memory controller exploitation in libvirt
Memory CGroup is a kernel feature that can be exploited effectively in the
current libvirt/qemu driver. Here is a shot at that.
At present, QEmu uses memory ballooning feature, where the memory can be
inflated/deflated as and when needed, co-operatively between the host and
the guest. There should be some mechanism where the host can have more
control over the guests memory usage. Memory CGroup provides features such
as hard-limit and soft-limit for memory, and hard-limit for swap area.
Design 1: Provide new API and XML changes for resource management
=================================================================
All the memory controller tunables are not supported with the current
abstractions provided by the libvirt API. libvirt works on various OS. This
new API will support GNU/Linux initially and as and when other platforms
starts supporting memory tunables, the interface could be enabled for
them. Adding following two function pointer to the virDriver interface.
1) domainSetMemoryParameters: which would take one or more name-value
pairs. This makes the API extensible, and agnostic to the kind of
parameters supported by various Hypervisors.
2) domainGetMemoryParameters: For getting current memory parameters
Corresponding libvirt public API:
int virDomainSetMemoryParamters (virDomainPtr domain,
virMemoryParamterPtr params,
unsigned int nparams);
int virDomainGetMemoryParamters (virDomainPtr domain,
virMemoryParamterPtr params,
unsigned int nparams);
Parameter list supported:
MemoryHardLimits (memory.limits_in_bytes) - Maximum memory
MemorySoftLimits (memory.softlimit_in_bytes) - Desired memory
MemoryMinimumGaurantee - Minimum memory required (without this amount of
memory, VM should not be started)
SwapHardLimits (memory.memsw_limit_in_bytes) - Maximum swap
SwapSoftLimits (Currently not supported by kernel) - Desired swap space
Tunables memory.limit_in_bytes, memory.softlimit_in_bytes and
memory.memsw_limit_in_bytes are provided by the memory controller in the
Linux kernel.
I am not an expert here, so just listing what new elements need to be added
to the XML schema:
<define name="resource">
<element memory>
<element memoryHardLimit/>
<element memorySoftLimit/>
<element memoryMinGaurantee/>
<element swapHardLimit/>
<element swapSoftLimit/>
</element>
</define>
Pros:
* Support all the tunables exported by the kernel
* More tunables can be added as and when required
Cons:
* Code changes would touch various levels
* Might need to redefine(changing the scope) of existing memory
API. Currently, domainSetMemory is used to set limit_in_bytes in LXC and
memory ballooning in QEmu. While the domainSetMaxMemory is not defined in
QEmu and in case of LXC it is setting the internal object's maxmem
variable.
Future:
* Later on, CPU/IO/Network controllers related tunables can be
added/enhanced along with the APIs/XML elements:
CPUHardLimit
CPUSoftLimit
CPUShare
CPUPercentage
IO_BW_Softlimit
IO_BW_Hardlimit
IO_BW_percentage
* libvirt-cim support for resource management
Design 2: Reuse the current memory APIs in libvirt
==================================================
Use memory.limit_in_bytes to tweak memory hard limits
Init - Set the memory.limit_in_bytes to maximum mem.
Claiming memory from guest:
a) Reduce balloon size
b) If the guest does not co-operate(How do we know?), reduce
memory.limit_in_bytes.
Allocating memory more than max memory: How to solve this? As we have
already set the max balloon size. We can only play within this!
Pros:
* Few changes
* Is not intrusive
Cons:
* SetMemory and SetMaxMemory usage is confusing.
* SetMemory is too generic a name, it does not cover all the tunables.
* Does not support memory softlimit
* Does not have support to reserve the memory swap region
* This solution is not extensible
IMO, "Design 1" is more generic and extensible for various memory
tuneables.
Nikunj
14 years, 7 months
[libvirt] [PATCH] esx: Map the .vmx annotation to the domain XML description
by Matthias Bolte
Take care of escaping '"' and '|' (the escape character).
Add tests for this.
---
src/esx/esx_vmx.c | 124 ++++++++++++++++++++++++-----
tests/vmx2xmldata/vmx2xml-annotation.vmx | 3 +
tests/vmx2xmldata/vmx2xml-annotation.xml | 16 ++++
tests/vmx2xmltest.c | 2 +
tests/xml2vmxdata/xml2vmx-annotation.vmx | 10 +++
tests/xml2vmxdata/xml2vmx-annotation.xml | 9 ++
tests/xml2vmxtest.c | 2 +
7 files changed, 144 insertions(+), 22 deletions(-)
create mode 100644 tests/vmx2xmldata/vmx2xml-annotation.vmx
create mode 100644 tests/vmx2xmldata/vmx2xml-annotation.xml
create mode 100644 tests/xml2vmxdata/xml2vmx-annotation.vmx
create mode 100644 tests/xml2vmxdata/xml2vmx-annotation.xml
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index 12cd005..bb86b4d 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -843,6 +843,9 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx,
long long numvcpus = 0;
char *sched_cpu_affinity = NULL;
char *guestOS = NULL;
+ char *annotation = NULL;
+ char *tmp;
+ int length;
int controller;
int bus;
int port;
@@ -947,6 +950,33 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx,
goto cleanup;
}
+ /* vmx:annotation -> def:description */
+ if (esxUtil_GetConfigString(conf, "annotation", &def->description,
+ true) < 0) {
+ goto cleanup;
+ }
+
+ /* Replace '|22' with '"' and '|7C' with '|' */
+ if (def->description != NULL) {
+ length = strlen(def->description) + 1;
+ tmp = def->description;
+
+ while (*tmp != '\0') {
+ if (STRPREFIX(tmp, "|22")) {
+ *tmp = '"';
+ memmove(tmp + 1, tmp + 3, length - 3);
+ length -= 2;
+ } else if (STRPREFIX(tmp, "|7C") || STRPREFIX(tmp, "|7c")) {
+ *tmp = '|';
+ memmove(tmp + 1, tmp + 3, length - 3);
+ length -= 2;
+ }
+
+ ++tmp;
+ --length;
+ }
+ }
+
/* vmx:memsize -> def:maxmem */
if (esxUtil_GetConfigLong(conf, "memsize", &memsize, 32, true) < 0) {
goto cleanup;
@@ -1304,6 +1334,7 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx,
virConfFree(conf);
VIR_FREE(sched_cpu_affinity);
VIR_FREE(guestOS);
+ VIR_FREE(annotation);
return def;
}
@@ -2314,10 +2345,15 @@ char *
esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
esxVI_ProductVersion productVersion)
{
+ char *vmx = NULL;
int i;
int sched_cpu_affinity_length;
unsigned char zero[VIR_UUID_BUFLEN];
virBuffer buffer = VIR_BUFFER_INITIALIZER;
+ int length;
+ char *tmp1;
+ char *tmp2;
+ char *annotation = NULL;
bool scsi_present[4] = { false, false, false, false };
int scsi_virtualDev[4] = { -1, -1, -1, -1 };
bool floppy_present[2] = { false, false };
@@ -2361,7 +2397,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
default:
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unexpected product version"));
- goto failure;
+ goto cleanup;
}
/* def:arch -> vmx:guestOS */
@@ -2373,7 +2409,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting domain XML attribute 'arch' of entry 'os/type' "
"to be 'i686' or 'x86_64' but found '%s'"), def->os.arch);
- goto failure;
+ goto cleanup;
}
/* def:uuid -> vmx:uuid.action, vmx:uuid.bios */
@@ -2392,13 +2428,53 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
/* def:name -> vmx:displayName */
virBufferVSprintf(&buffer, "displayName = \"%s\"\n", def->name);
+ /* def:description -> vmx:annotation */
+ if (def->description != NULL) {
+ /* Replace '"' with '|22' and '|' with '|7C' */
+ length = 1; /* 1 byte for termination */
+ tmp1 = def->description;
+
+ while (*tmp1 != '\0') {
+ if (*tmp1 == '"' || *tmp1 == '|') {
+ length += 2;
+ }
+
+ ++tmp1;
+ ++length;
+ }
+
+ if (VIR_ALLOC_N(annotation, length) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ tmp1 = def->description;
+ tmp2 = annotation;
+
+ while (*tmp1 != '\0') {
+ if (*tmp1 == '"') {
+ *tmp2++ = '|'; *tmp2++ = '2'; *tmp2++ = '2';
+ } else if (*tmp1 == '|') {
+ *tmp2++ = '|'; *tmp2++ = '7'; *tmp2++ = 'C';
+ } else {
+ *tmp2++ = *tmp1;
+ }
+
+ ++tmp1;
+ }
+
+ *tmp2 = '\0';
+
+ virBufferVSprintf(&buffer, "annotation = \"%s\"\n", annotation);
+ }
+
/* def:maxmem -> vmx:memsize */
if (def->maxmem <= 0 || def->maxmem % 4096 != 0) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting domain XML entry 'memory' to be an unsigned "
"integer (multiple of 4096) but found %lld"),
(unsigned long long)def->maxmem);
- goto failure;
+ goto cleanup;
}
/* Scale from kilobytes to megabytes */
@@ -2412,7 +2488,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
_("Expecting domain XML entry 'currentMemory' to be an "
"unsigned integer (multiple of 1024) but found %lld"),
(unsigned long long)def->memory);
- goto failure;
+ goto cleanup;
}
/* Scale from kilobytes to megabytes */
@@ -2426,7 +2502,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
_("Expecting domain XML entry 'vcpu' to be an unsigned "
"integer (1 or a multiple of 2) but found %d"),
(int)def->vcpus);
- goto failure;
+ goto cleanup;
}
virBufferVSprintf(&buffer, "numvcpus = \"%d\"\n", (int)def->vcpus);
@@ -2448,7 +2524,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
_("Expecting domain XML attribute 'cpuset' of entry "
"'vcpu' to contains at least %d CPU(s)"),
(int)def->vcpus);
- goto failure;
+ goto cleanup;
}
for (i = 0; i < def->cpumasklen; ++i) {
@@ -2471,7 +2547,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
switch (def->graphics[i]->type) {
case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
if (esxVMX_FormatVNC(def->graphics[i], &buffer) < 0) {
- goto failure;
+ goto cleanup;
}
break;
@@ -2480,7 +2556,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Unsupported graphics type '%s'"),
virDomainGraphicsTypeToString(def->graphics[i]->type));
- goto failure;
+ goto cleanup;
}
}
@@ -2488,13 +2564,13 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
for (i = 0; i < def->ndisks; ++i) {
if (esxVMX_VerifyDiskAddress(caps, def->disks[i]) < 0 ||
esxVMX_HandleLegacySCSIDiskDriverName(def, def->disks[i]) < 0) {
- goto failure;
+ goto cleanup;
}
}
if (esxVMX_GatherSCSIControllers(ctx, def, scsi_virtualDev,
scsi_present) < 0) {
- goto failure;
+ goto cleanup;
}
for (i = 0; i < 4; ++i) {
@@ -2513,14 +2589,14 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
switch (def->disks[i]->device) {
case VIR_DOMAIN_DISK_DEVICE_DISK:
if (esxVMX_FormatHardDisk(ctx, def->disks[i], &buffer) < 0) {
- goto failure;
+ goto cleanup;
}
break;
case VIR_DOMAIN_DISK_DEVICE_CDROM:
if (esxVMX_FormatCDROM(ctx, def->disks[i], &buffer) < 0) {
- goto failure;
+ goto cleanup;
}
break;
@@ -2528,7 +2604,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
if (esxVMX_FormatFloppy(ctx, def->disks[i], &buffer,
floppy_present) < 0) {
- goto failure;
+ goto cleanup;
}
break;
@@ -2537,7 +2613,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Unsupported disk device type '%s'"),
virDomainDiskDeviceTypeToString(def->disks[i]->device));
- goto failure;
+ goto cleanup;
}
}
@@ -2554,7 +2630,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
/* def:nets */
for (i = 0; i < def->nnets; ++i) {
if (esxVMX_FormatEthernet(def->nets[i], i, &buffer) < 0) {
- goto failure;
+ goto cleanup;
}
}
@@ -2570,29 +2646,33 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
/* def:serials */
for (i = 0; i < def->nserials; ++i) {
if (esxVMX_FormatSerial(ctx, def->serials[i], &buffer) < 0) {
- goto failure;
+ goto cleanup;
}
}
/* def:parallels */
for (i = 0; i < def->nparallels; ++i) {
if (esxVMX_FormatParallel(ctx, def->parallels[i], &buffer) < 0) {
- goto failure;
+ goto cleanup;
}
}
/* Get final VMX output */
if (virBufferError(&buffer)) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
- return virBufferContentAndReset(&buffer);
+ vmx = virBufferContentAndReset(&buffer);
- failure:
- virBufferFreeAndReset(&buffer);
+ cleanup:
+ if (vmx == NULL) {
+ virBufferFreeAndReset(&buffer);
+ }
+
+ VIR_FREE(annotation);
- return NULL;
+ return vmx;
}
diff --git a/tests/vmx2xmldata/vmx2xml-annotation.vmx b/tests/vmx2xmldata/vmx2xml-annotation.vmx
new file mode 100644
index 0000000..1ac420c
--- /dev/null
+++ b/tests/vmx2xmldata/vmx2xml-annotation.vmx
@@ -0,0 +1,3 @@
+config.version = "8"
+virtualHW.version = "4"
+annotation = "Some |7Ctext|7C to test the |22escaping|22: |7C|7C|22|22|7C|7C|22|7C"
diff --git a/tests/vmx2xmldata/vmx2xml-annotation.xml b/tests/vmx2xmldata/vmx2xml-annotation.xml
new file mode 100644
index 0000000..37c6ca9
--- /dev/null
+++ b/tests/vmx2xmldata/vmx2xml-annotation.xml
@@ -0,0 +1,16 @@
+<domain type='vmware'>
+ <uuid>00000000-0000-0000-0000-000000000000</uuid>
+ <description>Some |text| to test the "escaping": ||""||"|</description>
+ <memory>32768</memory>
+ <currentMemory>32768</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686'>hvm</type>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ </devices>
+</domain>
diff --git a/tests/vmx2xmltest.c b/tests/vmx2xmltest.c
index 50e7d0c..67296d6 100644
--- a/tests/vmx2xmltest.c
+++ b/tests/vmx2xmltest.c
@@ -280,6 +280,8 @@ mymain(int argc, char **argv)
DO_TEST("gsx-in-the-wild-3", "gsx-in-the-wild-3", esxVI_ProductVersion_ESX35);
DO_TEST("gsx-in-the-wild-4", "gsx-in-the-wild-4", esxVI_ProductVersion_ESX35);
+ DO_TEST("annotation", "annotation", esxVI_ProductVersion_ESX35);
+
virCapabilitiesFree(caps);
return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
diff --git a/tests/xml2vmxdata/xml2vmx-annotation.vmx b/tests/xml2vmxdata/xml2vmx-annotation.vmx
new file mode 100644
index 0000000..d5bd4b4
--- /dev/null
+++ b/tests/xml2vmxdata/xml2vmx-annotation.vmx
@@ -0,0 +1,10 @@
+config.version = "8"
+virtualHW.version = "4"
+guestOS = "other"
+uuid.bios = "56 4d 9b ef ac d9 b4 e0-c8 f0 ae a8 b9 10 35 15"
+displayName = "annotation"
+annotation = "Some |7Ctext|7C to test the |22escaping|22: |7C|7C|22|22|7C|7C|22|7C"
+memsize = "4"
+numvcpus = "1"
+floppy0.present = "false"
+floppy1.present = "false"
diff --git a/tests/xml2vmxdata/xml2vmx-annotation.xml b/tests/xml2vmxdata/xml2vmx-annotation.xml
new file mode 100644
index 0000000..d33827d
--- /dev/null
+++ b/tests/xml2vmxdata/xml2vmx-annotation.xml
@@ -0,0 +1,9 @@
+<domain type='vmware'>
+ <name>annotation</name>
+ <uuid>564d9bef-acd9-b4e0-c8f0-aea8b9103515</uuid>
+ <description>Some |text| to test the "escaping": ||""||"|</description>
+ <memory>4096</memory>
+ <os>
+ <type>hvm</type>
+ </os>
+</domain>
diff --git a/tests/xml2vmxtest.c b/tests/xml2vmxtest.c
index 71ce14a..2a457b4 100644
--- a/tests/xml2vmxtest.c
+++ b/tests/xml2vmxtest.c
@@ -273,6 +273,8 @@ mymain(int argc, char **argv)
DO_TEST("gsx-in-the-wild-3", "gsx-in-the-wild-3", esxVI_ProductVersion_ESX35);
DO_TEST("gsx-in-the-wild-4", "gsx-in-the-wild-4", esxVI_ProductVersion_ESX35);
+ DO_TEST("annotation", "annotation", esxVI_ProductVersion_ESX35);
+
virCapabilitiesFree(caps);
return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
--
1.7.0.4
14 years, 7 months
[libvirt] how to print size_t in LGPLv2+ program
by Eric Blake
libvirt is currently LGPLv2+, but needs to use the printf family of
functions to display size_t values, even on mingw where %zu support is
not built in. My understanding is that on 64-bit windows,
sizeof(long)==4 but sizeof(void*)==8; and if I'm reading
http://msdn.microsoft.com/en-us/library/s3f49ktz%28VS.80%29.aspx
correctly, then sizeof(size_t) is also 8. Which means you _can't_ use
"%lu",(unsigned long)size_t_val. And mingw also lacks support for
"%llu",(unsigned long long)size_t_val.
So that leaves several options:
Is it worth relaxing the license on the *printf-posix family of modules
to LGPLv2+ from their current LGPLv3+, or is this too big of a request?
Ultimately, this is the nicest - %zu would just work.
Is it worth relaxing the license of the inttostr family of modules?.
But that is also LGPLv3+, and requires a more careful audit to convert
all uses of "%zu",size_t_val into "%s",umaxtostr(size_t_val,buf). Or,
since using umaxtostr penalizes 32-bit machines for converting to the
64-bit intermediary, maybe it's worth adding a size_t variant? That,
and coreutils has a TODO to remove use of umaxtostr in favor of
<inttypes.h> solutions.
Finally, within existing LGPLv2+ modules, it is possible for libvirt to
manually use "%"PRIuMAX,(uintmax_t)size_t_val everywhere by relying on
gnulib's <inttypes.h> replacement, but that's also a painful audit to
perform and maintain, and also wastes processor cycles on 32-bit
machines for converting to the 64-bit intermediary.
What a shame that POSIX omitted an <inttypes.h> PRIu* for size_t.
--
Eric Blake eblake(a)redhat.com +1-801-349-2682
Libvirt virtualization library http://libvirt.org
14 years, 7 months
[libvirt] Xencaptest.c failing?
by Thomas Graves
Hello,
We are running xen3.4.3 on rhel5.4 and trying to build the new libvirt 0.8.3
and the xencaptest is failing.
It seems to be failing because it is passing NULL in as the virtconn and it
ends up going into the following code section in function
xenHypervisorBuildCapabilities:
if (sys_interface_version >= SYS_IFACE_MIN_VERS_NUMA) {
if (xenDaemonNodeGetTopology(conn, caps) != 0) {
virCapabilitiesFree(caps);
return NULL;
}
}
And that throws an error because conn is empty. I don't see how that could
ever work with the virtconn NULL. If I force it to be lower version number
then it passes fine. I think its figuring we are sys_interface_version=6.
Any ideas?
Thanks,
Tom
14 years, 7 months
[libvirt] Technical review of new libvirt TLS doco needed
by Justin Clift
Hi all,
Does someone have the time/inclination to review these new libvirt docs,
showing how to set up TLS, for technical accuracy?
Creating the Certificate Authority Cert
http://wiki.libvirt.org/page/TLSCreateCACertSteps
Creating the Server Certs
http://wiki.libvirt.org/page/TLSCreateServerCerts
Creating the Client Certs
http://wiki.libvirt.org/page/TLSCreateClientCerts
Configuring libvirt for TLS
http://wiki.libvirt.org/page/TLSDaemonConfiguration
Further References
http://wiki.libvirt.org/page/TLSFurtherReferences
They still need a few pics added, but thought it best to start getting
this looked at now. :)
There's also a high level concept page, to be used as an intro to the
above, here:
http://wiki.libvirt.org/page/HostCommTLSSetup
It only has draft pics atm, still needing to be given words and life.
Any takers, thoughts, input, etc?
Regards and best wishes,
Justin Clift
14 years, 7 months
[libvirt] How to override TLS client cert and key locations used for migration?
by Justin Clift
Hi guys,
Does anyone know if it's possible to override the default locations used
for the TLS client certificate and it's private key, as used in migration?
We have overrides in libvirtd.conf for the server cert and its private
key, but I'm not seeing anything for the corresponding client pieces.
The remote driver appears hard coded to use the default locations only:
src/remote/remote_driver.c
src/remote/remote_driver.h
Any ideas?
Regards and best wishes,
Justin Clift
14 years, 7 months
[libvirt] [PATCH] maint: turn on gcc logical-op checking
by Eric Blake
This would have detected the bug in commit 38ad33931 (Aug 09), which
we missed until commit f828ca35 (Jul 10); over 11 months later.
However, on Fedora 13, it also triggers LOTS of warnings from
the libcurl-devel header for one file:
esx/esx_vi.c: In function 'esxVI_CURL_Perform':
esx/esx_vi.c:232: error: logical '&&' with non-zero constant will always evaluate as true [-Wlogical-op]
esx/esx_vi.c:232: error: logical '&&' with non-zero constant will always evaluate as true [-Wlogical-op]
esx/esx_vi.c:232: error: logical '&&' with non-zero constant will always evaluate as true [-Wlogical-op]
...
I figure the gross hack to disable the warnings in the third-party
code, along with the reduction in type-safety in just esx_vi.c,
is worth the improved compiler checking throughout the rest of libvirt.
* acinclude.m4 (--enable-compile-warnings=error): Add
-Wlogical-op.
* src/esx/esx_vi.c (includes): Hack around broken libcurl-devel
header, to avoid compilation warning.
Suggested by Daniel P. Berrange.
---
In response to
https://www.redhat.com/archives/libvir-list/2010-July/msg00497.html
and fixing some long lines while I was at it.
acinclude.m4 | 16 +++++++++++++---
src/esx/esx_vi.c | 10 ++++++++++
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/acinclude.m4 b/acinclude.m4
index 8c97184..838ec46 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -36,9 +36,19 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[
try_compiler_flags="-Wall -Wformat -Wformat-security -Wmissing-prototypes $common_flags"
;;
maximum|error)
- try_compiler_flags="-Wall -Wformat -Wformat-security -Wmissing-prototypes -Wnested-externs -Wpointer-arith"
- try_compiler_flags="$try_compiler_flags -Wextra -Wshadow -Wcast-align -Wwrite-strings -Waggregate-return"
- try_compiler_flags="$try_compiler_flags -Wstrict-prototypes -Winline -Wredundant-decls -Wno-sign-compare"
+ try_compiler_flags="-Wall -Wformat -Wformat-security"
+ try_compiler_flags="$try_compiler_flags -Wmissing-prototypes"
+ try_compiler_flags="$try_compiler_flags -Wnested-externs "
+ try_compiler_flags="$try_compiler_flags -Wpointer-arith"
+ try_compiler_flags="$try_compiler_flags -Wextra -Wshadow"
+ try_compiler_flags="$try_compiler_flags -Wcast-align"
+ try_compiler_flags="$try_compiler_flags -Wwrite-strings"
+ try_compiler_flags="$try_compiler_flags -Waggregate-return"
+ try_compiler_flags="$try_compiler_flags -Wstrict-prototypes"
+ try_compiler_flags="$try_compiler_flags -Winline"
+ try_compiler_flags="$try_compiler_flags -Wredundant-decls"
+ try_compiler_flags="$try_compiler_flags -Wno-sign-compare"
+ try_compiler_flags="$try_compiler_flags -Wlogical-op"
try_compiler_flags="$try_compiler_flags $common_flags"
if test "$enable_compile_warnings" = "error" ; then
try_compiler_flags="$try_compiler_flags -Werror"
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 8c43d67..9ea8d24 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -36,6 +36,16 @@
#include "esx_vi_methods.h"
#include "esx_util.h"
+
+/* XXX "esx_vi.h" includes <curl/curl.h>; as of
+ * libcurl-devel-7.20.1-3.fc13.x86_64, curl ships a version of this
+ * header that #defines several wrapper macros around underlying
+ * functions to add type safety for gcc only. However, these macros
+ * spuriously trip gcc's -Wlogical-op warning. Avoid the warning by
+ * nuking the wrappers; even if it removes some type-check safety. */
+# undef curl_easy_getinfo
+# undef curl_easy_setopt
+
#define VIR_FROM_THIS VIR_FROM_ESX
--
1.7.1.1
14 years, 7 months
[libvirt] [PATCH] PHYP: Bad comparison when checking for existing domain name
by Eduardo Otubo
When creating a new domain from an XML, the check for an existing
domain name should compare the return of the function to a a valid
LPAR ID (!= -1) and not to error (== -1).
---
src/phyp/phyp_driver.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index 251111d..8eeba73 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -3759,7 +3759,7 @@ phypDomainCreateAndStart(virConnectPtr conn,
goto err;
/* checking if this name already exists on this system */
- if (phypGetLparID(session, managed_system, def->name, conn) == -1) {
+ if (phypGetLparID(session, managed_system, def->name, conn) != -1) {
VIR_WARN0("LPAR name already exists.");
goto err;
}
--
1.7.0.4
14 years, 7 months
[libvirt] [PATCH] esx: Fix esxVI_BuildSelectSet's invalid argument check
by Matthias Bolte
The check was altered in 8c48743b9737ad4d246ab6043fd299316f9a2091
and got too strict, I've no clue how that snuck in. This check
makes every try to open a connection using the ESX driver fail
with an invalid argument error.
Revert the change to the check and add a comment to prevent future
mistakes with this check.
---
src/esx/esx_vi.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 1c6f6ff..2359e8f 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -1390,7 +1390,11 @@ esxVI_BuildSelectSet(esxVI_SelectionSpec **selectSet,
esxVI_SelectionSpec *selectionSpec = NULL;
const char *currentSelectSetName = NULL;
- if (selectSet == NULL || *selectSet != NULL) {
+ if (selectSet == NULL) {
+ /*
+ * Don't check for *selectSet != NULL here because selectSet is a list
+ * and might contain items already. This function appends to selectSet.
+ */
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
--
1.7.0.4
14 years, 7 months
[libvirt] [PATCH REPOST] esx: Add read-only storage volume access
by Matthias Bolte
This allows to list existing volumes and to retrieve information
about them.
---
src/esx/esx_driver.c | 112 +----------
src/esx/esx_storage_driver.c | 433 +++++++++++++++++++++++++++++++++++++++-
src/esx/esx_vi.c | 279 ++++++++++++++++++++++++++
src/esx/esx_vi.h | 9 +
src/esx/esx_vi_generator.input | 7 +
5 files changed, 724 insertions(+), 116 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index c6bd3b8..5eeee1b 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -348,19 +348,7 @@ esxAutodetectSCSIControllerModel(virDomainDiskDefPtr def, int *model,
{
int result = -1;
esxVMX_Data *data = opaque;
- char *datastoreName = NULL;
- char *directoryName = NULL;
- char *fileName = NULL;
- char *datastorePath = NULL;
- esxVI_String *propertyNameList = NULL;
- esxVI_ObjectContent *datastore = NULL;
- esxVI_ManagedObjectReference *hostDatastoreBrowser = NULL;
- esxVI_HostDatastoreBrowserSearchSpec *searchSpec = NULL;
- esxVI_VmDiskFileQuery *vmDiskFileQuery = NULL;
- esxVI_ManagedObjectReference *task = NULL;
- esxVI_TaskInfoState taskInfoState;
- esxVI_TaskInfo *taskInfo = NULL;
- esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL;
if (def->device != VIR_DOMAIN_DISK_DEVICE_DISK ||
@@ -375,87 +363,12 @@ esxAutodetectSCSIControllerModel(virDomainDiskDefPtr def, int *model,
return 0;
}
- if (esxUtil_ParseDatastorePath(def->src, &datastoreName, &directoryName,
- &fileName) < 0) {
- goto cleanup;
- }
-
- if (directoryName == NULL) {
- if (virAsprintf(&datastorePath, "[%s]", datastoreName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- } else {
- if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
- directoryName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- }
-
- /* Lookup HostDatastoreBrowser */
- if (esxVI_String_AppendValueToList(&propertyNameList, "browser") < 0 ||
- esxVI_LookupDatastoreByName(data->ctx, datastoreName, propertyNameList,
- &datastore,
- esxVI_Occurrence_RequiredItem) < 0 ||
- esxVI_GetManagedObjectReference(datastore, "browser",
- &hostDatastoreBrowser,
- esxVI_Occurrence_RequiredItem) < 0) {
- goto cleanup;
- }
-
- /* Build HostDatastoreBrowserSearchSpec */
- if (esxVI_HostDatastoreBrowserSearchSpec_Alloc(&searchSpec) < 0 ||
- esxVI_FileQueryFlags_Alloc(&searchSpec->details) < 0) {
- goto cleanup;
- }
-
- searchSpec->details->fileType = esxVI_Boolean_True;
- searchSpec->details->fileSize = esxVI_Boolean_False;
- searchSpec->details->modification = esxVI_Boolean_False;
-
- if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 ||
- esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 ||
- esxVI_FileQuery_AppendToList
- (&searchSpec->query,
- esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) {
- goto cleanup;
- }
-
- vmDiskFileQuery->details->diskType = esxVI_Boolean_False;
- vmDiskFileQuery->details->capacityKb = esxVI_Boolean_False;
- vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False;
- vmDiskFileQuery->details->controllerType = esxVI_Boolean_True;
- vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False;
-
- if (esxVI_String_Alloc(&searchSpec->matchPattern) < 0) {
+ if (esxVI_LookupFileInfoByDatastorePath(data->ctx, def->src, &fileInfo,
+ esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
- searchSpec->matchPattern->value = fileName;
-
- /* Search datastore for file */
- if (esxVI_SearchDatastore_Task(data->ctx, hostDatastoreBrowser,
- datastorePath, searchSpec, &task) < 0 ||
- esxVI_WaitForTaskCompletion(data->ctx, task, NULL, esxVI_Occurrence_None,
- esxVI_Boolean_False, &taskInfoState) < 0) {
- goto cleanup;
- }
-
- if (taskInfoState != esxVI_TaskInfoState_Success) {
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Could not serach in datastore '%s'"), datastoreName);
- goto cleanup;
- }
-
- if (esxVI_LookupTaskInfoByTask(data->ctx, task, &taskInfo) < 0 ||
- esxVI_HostDatastoreBrowserSearchResults_CastFromAnyType
- (taskInfo->result, &searchResults) < 0) {
- goto cleanup;
- }
-
- /* Interpret search result */
- vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(searchResults->file);
+ vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(fileInfo);
if (vmDiskFileInfo == NULL || vmDiskFileInfo->controllerType == NULL) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
@@ -485,22 +398,7 @@ esxAutodetectSCSIControllerModel(virDomainDiskDefPtr def, int *model,
result = 0;
cleanup:
- /* Don't double free fileName */
- if (searchSpec != NULL && searchSpec->matchPattern != NULL) {
- searchSpec->matchPattern->value = NULL;
- }
-
- VIR_FREE(datastoreName);
- VIR_FREE(directoryName);
- VIR_FREE(fileName);
- VIR_FREE(datastorePath);
- esxVI_String_Free(&propertyNameList);
- esxVI_ObjectContent_Free(&datastore);
- esxVI_ManagedObjectReference_Free(&hostDatastoreBrowser);
- esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec);
- esxVI_ManagedObjectReference_Free(&task);
- esxVI_TaskInfo_Free(&taskInfo);
- esxVI_HostDatastoreBrowserSearchResults_Free(&searchResults);
+ esxVI_FileInfo_Free(&fileInfo);
return result;
}
diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c
index 26747bb..af8876a 100644
--- a/src/esx/esx_storage_driver.c
+++ b/src/esx/esx_storage_driver.c
@@ -32,6 +32,7 @@
#include "logging.h"
#include "uuid.h"
#include "storage_conf.h"
+#include "storage_file.h"
#include "esx_private.h"
#include "esx_storage_driver.h"
#include "esx_vi.h"
@@ -310,6 +311,14 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+static virStoragePoolPtr
+esxStoragePoolLookupByVolume(virStorageVolPtr volume)
+{
+ return esxStoragePoolLookupByName(volume->conn, volume->pool);
+}
+
+
+
static int
esxStoragePoolRefresh(virStoragePoolPtr pool, unsigned int flags)
{
@@ -556,6 +565,411 @@ esxStoragePoolSetAutostart(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
static int
+esxStoragePoolNumberOfStorageVolumes(virStoragePoolPtr pool)
+{
+ bool success = false;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL;
+ esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ int count = 0;
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return -1;
+ }
+
+ if (esxVI_LookupDatastoreContentByDatastoreName(priv->primary, pool->name,
+ &searchResultsList) < 0) {
+ goto cleanup;
+ }
+
+ /* Interpret search result */
+ for (searchResults = searchResultsList; searchResults != NULL;
+ searchResults = searchResults->_next) {
+ for (fileInfo = searchResults->file; fileInfo != NULL;
+ fileInfo = fileInfo->_next) {
+ ++count;
+ }
+ }
+
+ success = true;
+
+ cleanup:
+ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
+
+ return success ? count : -1;
+}
+
+
+
+static int
+esxStoragePoolListStorageVolumes(virStoragePoolPtr pool, char **const names,
+ int maxnames)
+{
+ bool success = false;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL;
+ esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ char *datastoreName = NULL;
+ char *directoryName = NULL;
+ char *fileName = NULL;
+ char *prefix = NULL;
+ int count = 0;
+ int i;
+
+ if (names == NULL || maxnames < 0) {
+ ESX_ERROR(VIR_ERR_INVALID_ARG, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (maxnames == 0) {
+ return 0;
+ }
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return -1;
+ }
+
+ if (esxVI_LookupDatastoreContentByDatastoreName(priv->primary, pool->name,
+ &searchResultsList) < 0) {
+ goto cleanup;
+ }
+
+ /* Interpret search result */
+ for (searchResults = searchResultsList; searchResults != NULL;
+ searchResults = searchResults->_next) {
+ VIR_FREE(datastoreName);
+ VIR_FREE(directoryName);
+ VIR_FREE(fileName);
+ VIR_FREE(prefix);
+
+ if (esxUtil_ParseDatastorePath(searchResults->folderPath, &datastoreName,
+ &directoryName, &fileName) < 0) {
+ goto cleanup;
+ }
+
+ if (directoryName != NULL) {
+ if (virAsprintf(&prefix, "%s/%s", directoryName, fileName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else {
+ prefix = strdup(fileName);
+
+ if (prefix == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ for (fileInfo = searchResults->file; fileInfo != NULL;
+ fileInfo = fileInfo->_next) {
+ if (*prefix == '\0') {
+ names[count] = strdup(fileInfo->path);
+
+ if (names[count] == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else if (virAsprintf(&names[count], "%s/%s", prefix,
+ fileInfo->path) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ ++count;
+ }
+ }
+
+ success = true;
+
+ cleanup:
+ if (! success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+
+ count = -1;
+ }
+
+ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
+ VIR_FREE(datastoreName);
+ VIR_FREE(directoryName);
+ VIR_FREE(fileName);
+ VIR_FREE(prefix);
+
+ return count;
+}
+
+
+
+static virStorageVolPtr
+esxStorageVolumeLookupByName(virStoragePoolPtr pool, const char *name)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ char *datastorePath = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return NULL;
+ }
+
+ if (virAsprintf(&datastorePath, "[%s] %s", pool->name, name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
+ &fileInfo,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ volume = virGetStorageVol(pool->conn, pool->name, name, datastorePath);
+
+ cleanup:
+ VIR_FREE(datastorePath);
+ esxVI_FileInfo_Free(&fileInfo);
+
+ return volume;
+}
+
+
+
+static virStorageVolPtr
+esxStorageVolumeLookupByKeyOrPath(virConnectPtr conn, const char *keyOrPath)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = conn->storagePrivateData;
+ char *datastoreName = NULL;
+ char *directoryName = NULL;
+ char *fileName = NULL;
+ char *volumeName = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return NULL;
+ }
+
+ if (esxUtil_ParseDatastorePath(keyOrPath, &datastoreName, &directoryName,
+ &fileName) < 0) {
+ goto cleanup;
+ }
+
+ if (directoryName != NULL) {
+ if (virAsprintf(&volumeName, "%s/%s", directoryName, fileName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else {
+ volumeName = strdup(fileName);
+
+ if (volumeName == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ if (esxVI_LookupFileInfoByDatastorePath(priv->primary, keyOrPath, &fileInfo,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ volume = virGetStorageVol(conn, datastoreName, volumeName, keyOrPath);
+
+ cleanup:
+ VIR_FREE(datastoreName);
+ VIR_FREE(directoryName);
+ VIR_FREE(fileName);
+ VIR_FREE(volumeName);
+ esxVI_FileInfo_Free(&fileInfo);
+
+ return volume;
+}
+
+
+
+static int
+esxStorageVolumeGetInfo(virStorageVolPtr volume, virStorageVolInfoPtr info)
+{
+ int result = -1;
+ esxPrivate *priv = volume->conn->storagePrivateData;
+ char *datastorePath = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL;
+
+ memset(info, 0, sizeof (*info));
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return -1;
+ }
+
+ if (virAsprintf(&datastorePath, "[%s] %s", volume->pool, volume->name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
+ &fileInfo,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(fileInfo);
+
+ info->type = VIR_STORAGE_VOL_FILE;
+
+ if (vmDiskFileInfo != NULL) {
+ info->capacity = vmDiskFileInfo->capacityKb->value * 1024; /* Scale from kilobyte to byte */
+ info->allocation = vmDiskFileInfo->fileSize->value;
+ } else {
+ info->capacity = fileInfo->fileSize->value;
+ info->allocation = fileInfo->fileSize->value;
+ }
+
+ result = 0;
+
+ cleanup:
+ VIR_FREE(datastorePath);
+ esxVI_FileInfo_Free(&fileInfo);
+
+ return result;
+}
+
+
+
+static char *
+esxStorageVolumeDumpXML(virStorageVolPtr volume, unsigned int flags)
+{
+ esxPrivate *priv = volume->conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_DatastoreInfo *datastoreInfo = NULL;
+ virStoragePoolDef pool;
+ char *datastorePath = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL;
+ esxVI_IsoImageFileInfo *isoImageFileInfo = NULL;
+ esxVI_FloppyImageFileInfo *floppyImageFileInfo = NULL;
+ virStorageVolDef def;
+ char *xml = NULL;
+
+ virCheckFlags(0, NULL);
+
+ memset(&pool, 0, sizeof (pool));
+ memset(&def, 0, sizeof (def));
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return NULL;
+ }
+
+ /* Lookup storage pool type */
+ if (esxVI_String_AppendValueToList(&propertyNameList, "info") < 0 ||
+ esxVI_LookupDatastoreByName(priv->primary, volume->pool,
+ propertyNameList, &datastore,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "info")) {
+ if (esxVI_DatastoreInfo_CastFromAnyType(dynamicProperty->val,
+ &datastoreInfo) < 0) {
+ goto cleanup;
+ }
+
+ break;
+ }
+ }
+
+ if (esxVI_LocalDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
+ pool.type = VIR_STORAGE_POOL_DIR;
+ } else if (esxVI_NasDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
+ pool.type = VIR_STORAGE_POOL_NETFS;
+ } else if (esxVI_VmfsDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
+ pool.type = VIR_STORAGE_POOL_FS;
+ } else {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("DatastoreInfo has unexpected type"));
+ goto cleanup;
+ }
+
+ /* Lookup file info */
+ if (virAsprintf(&datastorePath, "[%s] %s", volume->pool, volume->name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
+ &fileInfo,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(fileInfo);
+ isoImageFileInfo = esxVI_IsoImageFileInfo_DynamicCast(fileInfo);
+ floppyImageFileInfo = esxVI_FloppyImageFileInfo_DynamicCast(fileInfo);
+
+ def.name = volume->name;
+ def.key = datastorePath;
+ def.type = VIR_STORAGE_VOL_FILE;
+ def.target.path = datastorePath;
+
+ if (vmDiskFileInfo != NULL) {
+ def.capacity = vmDiskFileInfo->capacityKb->value * 1024; /* Scale from kilobyte to byte */
+ def.allocation = vmDiskFileInfo->fileSize->value;
+
+ def.target.format = VIR_STORAGE_FILE_VMDK;
+ } else if (isoImageFileInfo != NULL) {
+ def.capacity = fileInfo->fileSize->value;
+ def.allocation = fileInfo->fileSize->value;
+
+ def.target.format = VIR_STORAGE_FILE_ISO;
+ } else if (floppyImageFileInfo != NULL) {
+ def.capacity = fileInfo->fileSize->value;
+ def.allocation = fileInfo->fileSize->value;
+
+ def.target.format = VIR_STORAGE_FILE_RAW;
+ } else {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("File '%s' has unknown type"), datastorePath);
+ goto cleanup;
+ }
+
+ xml = virStorageVolDefFormat(&pool, &def);
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+ esxVI_DatastoreInfo_Free(&datastoreInfo);
+ VIR_FREE(datastorePath);
+ esxVI_FileInfo_Free(&fileInfo);
+
+ return xml;
+}
+
+
+
+static char *
+esxStorageVolumeGetPath(virStorageVolPtr volume)
+{
+ char *path;
+
+ if (virAsprintf(&path, "[%s] %s", volume->pool, volume->name) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ return path;
+}
+
+
+
+static int
esxStoragePoolIsActive(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
{
/* ESX storage pools are always active */
@@ -572,6 +986,7 @@ esxStoragePoolIsPersistent(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
}
+
static virStorageDriver esxStorageDriver = {
"ESX", /* name */
esxStorageOpen, /* open */
@@ -583,7 +998,7 @@ static virStorageDriver esxStorageDriver = {
NULL, /* findPoolSources */
esxStoragePoolLookupByName, /* poolLookupByName */
esxStoragePoolLookupByUUID, /* poolLookupByUUID */
- NULL, /* poolLookupByVolume */
+ esxStoragePoolLookupByVolume, /* poolLookupByVolume */
NULL, /* poolCreateXML */
NULL, /* poolDefineXML */
NULL, /* poolBuild */
@@ -596,18 +1011,18 @@ static virStorageDriver esxStorageDriver = {
esxStoragePoolGetXMLDesc, /* poolGetXMLDesc */
esxStoragePoolGetAutostart, /* poolGetAutostart */
esxStoragePoolSetAutostart, /* poolSetAutostart */
- NULL, /* poolNumOfVolumes */
- NULL, /* poolListVolumes */
- NULL, /* volLookupByName */
- NULL, /* volLookupByKey */
- NULL, /* volLookupByPath */
+ esxStoragePoolNumberOfStorageVolumes, /* poolNumOfVolumes */
+ esxStoragePoolListStorageVolumes, /* poolListVolumes */
+ esxStorageVolumeLookupByName, /* volLookupByName */
+ esxStorageVolumeLookupByKeyOrPath, /* volLookupByKey */
+ esxStorageVolumeLookupByKeyOrPath, /* volLookupByPath */
NULL, /* volCreateXML */
NULL, /* volCreateXMLFrom */
NULL, /* volDelete */
NULL, /* volWipe */
- NULL, /* volGetInfo */
- NULL, /* volGetXMLDesc */
- NULL, /* volGetPath */
+ esxStorageVolumeGetInfo, /* volGetInfo */
+ esxStorageVolumeDumpXML, /* volGetXMLDesc */
+ esxStorageVolumeGetPath, /* volGetPath */
esxStoragePoolIsActive, /* poolIsActive */
esxStoragePoolIsPersistent, /* poolIsPersistent */
};
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 3773a5f..cb3d544 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -2933,6 +2933,285 @@ esxVI_LookupCurrentSnapshotTree
int
+esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx,
+ const char *datastorePath,
+ esxVI_FileInfo **fileInfo,
+ esxVI_Occurrence occurrence)
+{
+ int result = -1;
+ char *datastoreName = NULL;
+ char *directoryName = NULL;
+ char *fileName = NULL;
+ char *datastorePathWithoutFileName = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_ManagedObjectReference *hostDatastoreBrowser = NULL;
+ esxVI_HostDatastoreBrowserSearchSpec *searchSpec = NULL;
+ esxVI_VmDiskFileQuery *vmDiskFileQuery = NULL;
+ esxVI_IsoImageFileQuery *isoImageFileQuery = NULL;
+ esxVI_FloppyImageFileQuery *floppyImageFileQuery = NULL;
+ esxVI_ManagedObjectReference *task = NULL;
+ esxVI_TaskInfoState taskInfoState;
+ esxVI_TaskInfo *taskInfo = NULL;
+ esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
+
+ if (fileInfo == NULL || *fileInfo != NULL) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (esxUtil_ParseDatastorePath(datastorePath, &datastoreName,
+ &directoryName, &fileName) < 0) {
+ goto cleanup;
+ }
+
+ if (directoryName == NULL) {
+ if (virAsprintf(&datastorePathWithoutFileName, "[%s]",
+ datastoreName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else {
+ if (virAsprintf(&datastorePathWithoutFileName, "[%s] %s",
+ datastoreName, directoryName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ /* Lookup HostDatastoreBrowser */
+ if (esxVI_String_AppendValueToList(&propertyNameList, "browser") < 0 ||
+ esxVI_LookupDatastoreByName(ctx, datastoreName, propertyNameList,
+ &datastore,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_GetManagedObjectReference(datastore, "browser",
+ &hostDatastoreBrowser,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ /* Build HostDatastoreBrowserSearchSpec */
+ if (esxVI_HostDatastoreBrowserSearchSpec_Alloc(&searchSpec) < 0 ||
+ esxVI_FileQueryFlags_Alloc(&searchSpec->details) < 0) {
+ goto cleanup;
+ }
+
+ searchSpec->details->fileType = esxVI_Boolean_True;
+ searchSpec->details->fileSize = esxVI_Boolean_True;
+ searchSpec->details->modification = esxVI_Boolean_False;
+
+ if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 ||
+ esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) {
+ goto cleanup;
+ }
+
+ vmDiskFileQuery->details->diskType = esxVI_Boolean_False;
+ vmDiskFileQuery->details->capacityKb = esxVI_Boolean_True;
+ vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False;
+ vmDiskFileQuery->details->controllerType = esxVI_Boolean_True;
+ vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False;
+
+ if (esxVI_IsoImageFileQuery_Alloc(&isoImageFileQuery) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(isoImageFileQuery)) < 0) {
+ goto cleanup;
+ }
+
+ if (esxVI_FloppyImageFileQuery_Alloc(&floppyImageFileQuery) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(floppyImageFileQuery)) < 0) {
+ goto cleanup;
+ }
+
+ if (esxVI_String_Alloc(&searchSpec->matchPattern) < 0) {
+ goto cleanup;
+ }
+
+ searchSpec->matchPattern->value = fileName;
+
+ /* Search datastore for file */
+ if (esxVI_SearchDatastore_Task(ctx, hostDatastoreBrowser,
+ datastorePathWithoutFileName, searchSpec,
+ &task) < 0 ||
+ esxVI_WaitForTaskCompletion(ctx, task, NULL, esxVI_Occurrence_None,
+ esxVI_Boolean_False, &taskInfoState) < 0) {
+ goto cleanup;
+ }
+
+ if (taskInfoState != esxVI_TaskInfoState_Success) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not serach in datastore '%s'"), datastoreName);
+ goto cleanup;
+ }
+
+ if (esxVI_LookupTaskInfoByTask(ctx, task, &taskInfo) < 0 ||
+ esxVI_HostDatastoreBrowserSearchResults_CastFromAnyType
+ (taskInfo->result, &searchResults) < 0) {
+ goto cleanup;
+ }
+
+ /* Interpret search result */
+ if (searchResults->file == NULL) {
+ if (occurrence == esxVI_Occurrence_OptionalItem) {
+ result = 0;
+
+ goto cleanup;
+ } else {
+ ESX_VI_ERROR(VIR_ERR_NO_STORAGE_VOL,
+ _("No storage volume with key or path '%s'"),
+ datastorePath);
+ goto cleanup;
+ }
+ }
+
+ *fileInfo = searchResults->file;
+ searchResults->file = NULL;
+
+ result = 0;
+
+ cleanup:
+ /* Don't double free fileName */
+ if (searchSpec != NULL && searchSpec->matchPattern != NULL) {
+ searchSpec->matchPattern->value = NULL;
+ }
+
+ VIR_FREE(datastoreName);
+ VIR_FREE(directoryName);
+ VIR_FREE(fileName);
+ VIR_FREE(datastorePathWithoutFileName);
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+ esxVI_ManagedObjectReference_Free(&hostDatastoreBrowser);
+ esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec);
+ esxVI_ManagedObjectReference_Free(&task);
+ esxVI_TaskInfo_Free(&taskInfo);
+ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResults);
+
+ return result;
+}
+
+
+
+int
+esxVI_LookupDatastoreContentByDatastoreName
+ (esxVI_Context *ctx, const char *datastoreName,
+ esxVI_HostDatastoreBrowserSearchResults **searchResultsList)
+{
+ int result = -1;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_ManagedObjectReference *hostDatastoreBrowser = NULL;
+ esxVI_HostDatastoreBrowserSearchSpec *searchSpec = NULL;
+ esxVI_VmDiskFileQuery *vmDiskFileQuery = NULL;
+ esxVI_IsoImageFileQuery *isoImageFileQuery = NULL;
+ esxVI_FloppyImageFileQuery *floppyImageFileQuery = NULL;
+ char *datastorePath = NULL;
+ esxVI_ManagedObjectReference *task = NULL;
+ esxVI_TaskInfoState taskInfoState;
+ esxVI_TaskInfo *taskInfo = NULL;
+
+ if (searchResultsList == NULL || *searchResultsList != NULL) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ /* Lookup Datastore and HostDatastoreBrowser */
+ if (esxVI_String_AppendValueToList(&propertyNameList, "browser") < 0 ||
+ esxVI_LookupDatastoreByName(ctx, datastoreName, propertyNameList,
+ &datastore,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_GetManagedObjectReference(datastore, "browser",
+ &hostDatastoreBrowser,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ /* Build HostDatastoreBrowserSearchSpec */
+ if (esxVI_HostDatastoreBrowserSearchSpec_Alloc(&searchSpec) < 0 ||
+ esxVI_FileQueryFlags_Alloc(&searchSpec->details) < 0) {
+ goto cleanup;
+ }
+
+ searchSpec->details->fileType = esxVI_Boolean_True;
+ searchSpec->details->fileSize = esxVI_Boolean_True;
+ searchSpec->details->modification = esxVI_Boolean_False;
+
+ if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 ||
+ esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) {
+ goto cleanup;
+ }
+
+ vmDiskFileQuery->details->diskType = esxVI_Boolean_False;
+ vmDiskFileQuery->details->capacityKb = esxVI_Boolean_True;
+ vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False;
+ vmDiskFileQuery->details->controllerType = esxVI_Boolean_True;
+ vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False;
+
+ if (esxVI_IsoImageFileQuery_Alloc(&isoImageFileQuery) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(isoImageFileQuery)) < 0) {
+ goto cleanup;
+ }
+
+ if (esxVI_FloppyImageFileQuery_Alloc(&floppyImageFileQuery) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(floppyImageFileQuery)) < 0) {
+ goto cleanup;
+ }
+
+ /* Search datastore for files */
+ if (virAsprintf(&datastorePath, "[%s]", datastoreName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_SearchDatastoreSubFolders_Task(ctx, hostDatastoreBrowser,
+ datastorePath, searchSpec,
+ &task) < 0 ||
+ esxVI_WaitForTaskCompletion(ctx, task, NULL, esxVI_Occurrence_None,
+ esxVI_Boolean_False, &taskInfoState) < 0) {
+ goto cleanup;
+ }
+
+ if (taskInfoState != esxVI_TaskInfoState_Success) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not serach in datastore '%s'"), datastoreName);
+ goto cleanup;
+ }
+
+ if (esxVI_LookupTaskInfoByTask(ctx, task, &taskInfo) < 0 ||
+ esxVI_HostDatastoreBrowserSearchResults_CastListFromAnyType
+ (taskInfo->result, searchResultsList) < 0) {
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+ esxVI_ManagedObjectReference_Free(&hostDatastoreBrowser);
+ esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec);
+ VIR_FREE(datastorePath);
+ esxVI_ManagedObjectReference_Free(&task);
+ esxVI_TaskInfo_Free(&taskInfo);
+
+ return result;
+}
+
+
+
+int
esxVI_HandleVirtualMachineQuestion
(esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine,
esxVI_VirtualMachineQuestionInfo *questionInfo,
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index d5dc9d5..42f535f 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -397,6 +397,15 @@ int esxVI_LookupCurrentSnapshotTree
esxVI_VirtualMachineSnapshotTree **currentSnapshotTree,
esxVI_Occurrence occurrence);
+int esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx,
+ const char *datastorePath,
+ esxVI_FileInfo **fileInfo,
+ esxVI_Occurrence occurrence);
+
+int esxVI_LookupDatastoreContentByDatastoreName
+ (esxVI_Context *ctx, const char *datastoreName,
+ esxVI_HostDatastoreBrowserSearchResults **searchResultsList);
+
int esxVI_HandleVirtualMachineQuestion
(esxVI_Context *ctx,
esxVI_ManagedObjectReference *virtualMachine,
diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
index ab50ea5..0fb9448 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -813,6 +813,13 @@ method RevertToSnapshot_Task returns ManagedObjectReference r
end
+method SearchDatastoreSubFolders_Task returns ManagedObjectReference r
+ ManagedObjectReference _this r
+ String datastorePath r
+ HostDatastoreBrowserSearchSpec searchSpec o
+end
+
+
method SearchDatastore_Task returns ManagedObjectReference r
ManagedObjectReference _this r
String datastorePath r
--
1.7.0.4
14 years, 7 months