[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, 2 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, 2 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, 3 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, 3 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, 3 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, 3 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, 3 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, 3 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, 3 months
[libvirt] [PATCH] Move libvirt-guests init script and config to tools
by Jiri Denemark
Since libvirt-guests init script and its configuration do not require
libvirtd to be running/installed, it was a bad idea to put them into
daemon directory. libvirt.spec even includes these files in
libvirt-client subpackage, which may result in build failure for
client-only builds when the whole daemon directory is just skipped.
---
daemon/Makefile.am | 16 +--
daemon/libvirt-guests.init.in | 341 -----------------------------------------
daemon/libvirt-guests.sysconf | 24 ---
tools/Makefile.am | 41 +++++-
tools/libvirt-guests.init.in | 341 +++++++++++++++++++++++++++++++++++++++++
tools/libvirt-guests.sysconf | 24 +++
6 files changed, 409 insertions(+), 378 deletions(-)
delete mode 100644 daemon/libvirt-guests.init.in
delete mode 100644 daemon/libvirt-guests.sysconf
create mode 100644 tools/libvirt-guests.init.in
create mode 100644 tools/libvirt-guests.sysconf
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index dbf0ac3..53133d2 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -35,8 +35,6 @@ EXTRA_DIST = \
libvirtd.uml.logrotate.in \
test_libvirtd.aug \
THREADING.txt \
- libvirt-guests.init.in \
- libvirt-guests.sysconf \
libvirtd.pod.in \
$(AVAHI_SOURCES) \
$(DAEMON_SOURCES)
@@ -258,27 +256,21 @@ install-logrotate: $(LOGROTATE_CONFS)
$(INSTALL_DATA) libvirtd.uml.logrotate $(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd.uml
if LIBVIRT_INIT_SCRIPT_RED_HAT
-install-init: libvirtd.init libvirt-guests.init
+install-init: libvirtd.init
mkdir -p $(DESTDIR)$(sysconfdir)/rc.d/init.d
$(INSTALL_SCRIPT) libvirtd.init \
$(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirtd
- $(INSTALL_SCRIPT) libvirt-guests.init \
- $(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirt-guests
mkdir -p $(DESTDIR)$(sysconfdir)/sysconfig
$(INSTALL_SCRIPT) $(srcdir)/libvirtd.sysconf \
$(DESTDIR)$(sysconfdir)/sysconfig/libvirtd
- $(INSTALL_SCRIPT) $(srcdir)/libvirt-guests.sysconf \
- $(DESTDIR)$(sysconfdir)/sysconfig/libvirt-guests
uninstall-init:
rm -f $(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirtd \
- $(DESTDIR)$(sysconfdir)/sysconfig/libvirtd \
- $(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirt-guests \
- $(DESTDIR)$(sysconfdir)/sysconfig/libvirt-guests
+ $(DESTDIR)$(sysconfdir)/sysconfig/libvirtd
-BUILT_SOURCES += libvirtd.init libvirt-guests.init
+BUILT_SOURCES += libvirtd.init
-%.init: %.init.in $(top_builddir)/config.status
+libvirtd.init: libvirtd.init.in $(top_builddir)/config.status
$(AM_V_GEN)sed \
-e s!\@localstatedir\@!@localstatedir@!g \
-e s!\@sbindir\@!@sbindir@!g \
diff --git a/daemon/libvirt-guests.init.in b/daemon/libvirt-guests.init.in
deleted file mode 100644
index 993c12d..0000000
--- a/daemon/libvirt-guests.init.in
+++ /dev/null
@@ -1,341 +0,0 @@
-#!/bin/sh
-
-# the following is the LSB init header
-#
-### BEGIN INIT INFO
-# Provides: libvirt-guests
-# Required-Start: libvirtd
-# Required-Stop: libvirtd
-# Default-Start: 3 4 5
-# Short-Description: suspend/resume libvirt guests on shutdown/boot
-# Description: This is a script for suspending active libvirt guests
-# on shutdown and resuming them on next boot
-# See http://libvirt.org
-### END INIT INFO
-
-# the following is chkconfig init header
-#
-# libvirt-guests: suspend/resume libvirt guests on shutdown/boot
-#
-# chkconfig: 345 98 02
-# description: This is a script for suspending active libvirt guests \
-# on shutdown and resuming them on next boot \
-# See http://libvirt.org
-#
-
-sysconfdir=@sysconfdir@
-localstatedir=@localstatedir@
-libvirtd=@sbindir@/libvirtd
-
-# Source function library.
-. "$sysconfdir"/rc.d/init.d/functions
-
-URIS=default
-ON_BOOT=start
-ON_SHUTDOWN=suspend
-SHUTDOWN_TIMEOUT=0
-
-test -f "$sysconfdir"/sysconfig/libvirt-guests && . "$sysconfdir"/sysconfig/libvirt-guests
-
-LISTFILE="$localstatedir"/lib/libvirt/libvirt-guests
-VAR_SUBSYS_LIBVIRT_GUESTS="$localstatedir"/lock/subsys/libvirt-guests
-
-RETVAL=0
-
-retval() {
- "$@"
- if [ $? -ne 0 ]; then
- RETVAL=1
- return 1
- else
- return 0
- fi
-}
-
-run_virsh() {
- uri=$1
- shift
-
- if [ "x$uri" = xdefault ]; then
- conn=
- else
- conn="-c $uri"
- fi
-
- virsh $conn "$@" </dev/null
-}
-
-run_virsh_c() {
- ( export LC_ALL=C; run_virsh "$@" )
-}
-
-list_guests() {
- uri=$1
-
- list=$(run_virsh_c $uri list)
- if [ $? -ne 0 ]; then
- RETVAL=1
- return 1
- fi
-
- uuids=
- for id in $(echo "$list" | awk 'NR > 2 {print $1}'); do
- uuid=$(run_virsh_c $uri dominfo $id | awk '/^UUID:/{print $2}')
- if [ -z "$uuid" ]; then
- RETVAL=1
- return 1
- fi
- uuids="$uuids $uuid"
- done
-
- echo $uuids
-}
-
-guest_name() {
- uri=$1
- uuid=$2
-
- name=$(run_virsh_c $uri dominfo $uuid 2>/dev/null | \
- awk '/^Name:/{print $2}')
- [ -n "$name" ] || name=$uuid
-
- echo "$name"
-}
-
-guest_is_on() {
- uri=$1
- uuid=$2
-
- guest_running=false
- info=$(run_virsh_c $uri dominfo $uuid)
- if [ $? -ne 0 ]; then
- RETVAL=1
- return 1
- fi
-
- id=$(echo "$info" | awk '/^Id:/{print $2}')
-
- [ -n "$id" ] && [ "x$id" != x- ] && guest_running=true
- return 0
-}
-
-started() {
- touch "$VAR_SUBSYS_LIBVIRT_GUESTS"
-}
-
-start() {
- [ -f "$LISTFILE" ] || { started; return 0; }
-
- if [ "x$ON_BOOT" != xstart ]; then
- echo $"libvirt-guests is configured not to start any guests on boot"
- rm -f "$LISTFILE"
- started
- return 0
- fi
-
- while read uri list; do
- configured=false
- for confuri in $URIS; do
- if [ $confuri = $uri ]; then
- configured=true
- break
- fi
- done
- if ! $configured; then
- echo $"Ignoring guests on $uri URI"
- continue
- fi
-
- echo $"Resuming guests on $uri URI..."
- for guest in $list; do
- name=$(guest_name $uri $guest)
- echo -n $"Resuming guest $name: "
- if guest_is_on $uri $guest; then
- if $guest_running; then
- echo $"already active"
- else
- retval run_virsh $uri start "$name" >/dev/null && \
- echo $"done"
- fi
- fi
- done
- done <"$LISTFILE"
-
- rm -f "$LISTFILE"
- started
-}
-
-suspend_guest()
-{
- uri=$1
- guest=$2
-
- name=$(guest_name $uri $guest)
- label=$"Suspending $name: "
- echo -n "$label"
- run_virsh $uri managedsave $guest >/dev/null &
- virsh_pid=$!
- while true; do
- sleep 1
- kill -0 $virsh_pid >&/dev/null || break
- progress=$(run_virsh_c $uri domjobinfo $guest 2>/dev/null | \
- awk '/^Data processed:/{print $3, $4}')
- if [ -n "$progress" ]; then
- printf '\r%s%12s ' "$label" "$progress"
- else
- printf '\r%s%-12s ' "$label" "..."
- fi
- done
- retval wait $virsh_pid && printf '\r%s%-12s\n' "$label" $"done"
-}
-
-shutdown_guest()
-{
- uri=$1
- guest=$2
-
- name=$(guest_name $uri $guest)
- label=$"Shutting down $name: "
- echo -n "$label"
- retval run_virsh $uri shutdown $guest >/dev/null || return
- timeout=$SHUTDOWN_TIMEOUT
- while [ $timeout -gt 0 ]; do
- sleep 1
- timeout=$[timeout - 1]
- guest_is_on $uri $guest || return
- $guest_running || break
- printf '\r%s%-12d ' "$label" $timeout
- done
-
- if guest_is_on $uri $guest; then
- if $guest_running; then
- printf '\r%s%-12s\n' "$label" $"failed to shutdown in time"
- else
- printf '\r%s%-12s\n' "$label" $"done"
- fi
- fi
-}
-
-stop() {
- # last stop was not followed by start
- [ -f "$LISTFILE" ] && return 0
-
- suspending=true
- if [ "x$ON_SHUTDOWN" = xshutdown ]; then
- suspending=false
- if [ $SHUTDOWN_TIMEOUT -le 0 ]; then
- echo $"Shutdown action requested but SHUTDOWN_TIMEOUT was not set"
- RETVAL=6
- return
- fi
- fi
-
- : >"$LISTFILE"
- for uri in $URIS; do
- echo -n $"Running guests on $uri URI: "
-
- if [ "x$uri" = xdefault ] && [ ! -x "$libvirtd" ]; then
- echo $"libvirtd not installed; skipping this URI."
- continue
- fi
-
- list=$(list_guests $uri)
- if [ $? -eq 0 ]; then
- empty=true
- for uuid in $list; do
- $empty || printf ", "
- echo -n $(guest_name $uri $uuid)
- empty=false
- done
- if $empty; then
- echo $"no running guests."
- else
- echo
- echo $uri $list >>"$LISTFILE"
- fi
- fi
- done
-
- while read uri list; do
- if $suspending; then
- echo $"Suspending guests on $uri URI..."
- else
- echo $"Shutting down guests on $uri URI..."
- fi
-
- for guest in $list; do
- if $suspending; then
- suspend_guest $uri $guest
- else
- shutdown_guest $uri $guest
- fi
- done
- done <"$LISTFILE"
-
- rm -f "$VAR_SUBSYS_LIBVIRT_GUESTS"
-}
-
-gueststatus() {
- for uri in $URIS; do
- echo "* $uri URI:"
- retval run_virsh $uri list || echo
- done
-}
-
-# rh_status
-# Display current status: whether saved state exists, and whether start
-# has been executed. We cannot use status() from the functions library,
-# since there is no external daemon process matching this init script.
-rh_status() {
- if [ -f "$LISTFILE" ]; then
- echo $"stopped, with saved guests"
- RETVAL=3
- else
- if [ -f "$VAR_SUBSYS_LIBVIRT_GUESTS" ]; then
- echo $"started"
- else
- echo $"stopped, with no saved guests"
- fi
- RETVAL=0
- fi
-}
-
-# usage [val]
-# Display usage string, then exit with VAL (defaults to 2).
-usage() {
- echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|gueststatus|shutdown}"
- exit ${1-2}
-}
-
-# See how we were called.
-if test $# != 1; then
- usage
-fi
-case "$1" in
- --help)
- usage 0
- ;;
- start|stop|gueststatus)
- $1
- ;;
- restart)
- stop && start
- ;;
- condrestart|try-restart)
- [ -f "$VAR_SUBSYS_LIBVIRT_GUESTS" ] && stop && start
- ;;
- reload|force-reload)
- # Nothing to do; we reread configuration on each invocation
- ;;
- status)
- rh_status
- ;;
- shutdown)
- ON_SHUTDOWN=shutdown
- stop
- ;;
- *)
- usage
- ;;
-esac
-exit $RETVAL
diff --git a/daemon/libvirt-guests.sysconf b/daemon/libvirt-guests.sysconf
deleted file mode 100644
index cd58728..0000000
--- a/daemon/libvirt-guests.sysconf
+++ /dev/null
@@ -1,24 +0,0 @@
-# URIs to check for running guests
-# example: URIS='default xen:/// vbox+tcp://host/system lxc:///'
-#URIS=default
-
-# action taken on host boot
-# - start all guests which were running on shutdown are started on boot
-# regardless on their autostart settings
-# - ignore libvirt-guests init script won't start any guest on boot, however,
-# guests marked as autostart will still be automatically started by
-# libvirtd
-#ON_BOOT=start
-
-# action taken on host shutdown
-# - suspend all running guests are suspended using virsh managedsave
-# - shutdown all running guests are asked to shutdown. Please be careful with
-# this settings since there is no way to distinguish between a
-# guest which is stuck or ignores shutdown requests and a guest
-# which just needs a long time to shutdown. When setting
-# ON_SHUTDOWN=shutdown, you must also set SHUTDOWN_TIMEOUT to a
-# value suitable for your guests.
-#ON_SHUTDOWN=suspend
-
-# number of seconds we're willing to wait for a guest to shut down
-#SHUTDOWN_TIMEOUT=0
diff --git a/tools/Makefile.am b/tools/Makefile.am
index fd05e8b..ac26cae 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -8,7 +8,13 @@ ICON_FILES = \
libvirt_win_icon_64x64.ico \
virsh_win_icon.rc
-EXTRA_DIST = $(ICON_FILES) virt-xml-validate.in virt-pki-validate.in virsh.pod
+EXTRA_DIST = \
+ $(ICON_FILES) \
+ virt-xml-validate.in \
+ virt-pki-validate.in \
+ virsh.pod \
+ libvirt-guests.init.in \
+ libvirt-guests.sysconf
bin_SCRIPTS = virt-xml-validate virt-pki-validate
bin_PROGRAMS = virsh
@@ -118,6 +124,39 @@ endif
virsh.1: virsh.pod
$(AM_V_GEN)$(POD2MAN) $< $@
+install-data-local: install-init
+
+uninstall-local: uninstall-init
+
+if LIBVIRT_INIT_SCRIPT_RED_HAT
+install-init: libvirt-guests.init
+ mkdir -p $(DESTDIR)$(sysconfdir)/rc.d/init.d
+ $(INSTALL_SCRIPT) libvirt-guests.init \
+ $(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirt-guests
+ mkdir -p $(DESTDIR)$(sysconfdir)/sysconfig
+ $(INSTALL_SCRIPT) $(srcdir)/libvirt-guests.sysconf \
+ $(DESTDIR)$(sysconfdir)/sysconfig/libvirt-guests
+
+uninstall-init:
+ rm -f $(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirt-guests \
+ $(DESTDIR)$(sysconfdir)/sysconfig/libvirt-guests
+
+BUILT_SOURCES += libvirt-guests.init
+
+libvirt-guests.init: libvirt-guests.init.in $(top_builddir)/config.status
+ $(AM_V_GEN)sed \
+ -e s!\@localstatedir\@!@localstatedir@!g \
+ -e s!\@sbindir\@!@sbindir@!g \
+ -e s!\@sysconfdir\@!@sysconfdir@!g \
+ < $< > $@-t && \
+ chmod a+x $@-t && \
+ mv $@-t $@
+else
+install-init:
+uninstall-init:
+libvirt-guests.init:
+endif # LIBVIRT_INIT_SCRIPT_RED_HAT
+
CLEANFILES = $(bin_SCRIPTS) $(man1_MANS)
diff --git a/tools/libvirt-guests.init.in b/tools/libvirt-guests.init.in
new file mode 100644
index 0000000..993c12d
--- /dev/null
+++ b/tools/libvirt-guests.init.in
@@ -0,0 +1,341 @@
+#!/bin/sh
+
+# the following is the LSB init header
+#
+### BEGIN INIT INFO
+# Provides: libvirt-guests
+# Required-Start: libvirtd
+# Required-Stop: libvirtd
+# Default-Start: 3 4 5
+# Short-Description: suspend/resume libvirt guests on shutdown/boot
+# Description: This is a script for suspending active libvirt guests
+# on shutdown and resuming them on next boot
+# See http://libvirt.org
+### END INIT INFO
+
+# the following is chkconfig init header
+#
+# libvirt-guests: suspend/resume libvirt guests on shutdown/boot
+#
+# chkconfig: 345 98 02
+# description: This is a script for suspending active libvirt guests \
+# on shutdown and resuming them on next boot \
+# See http://libvirt.org
+#
+
+sysconfdir=@sysconfdir@
+localstatedir=@localstatedir@
+libvirtd=@sbindir@/libvirtd
+
+# Source function library.
+. "$sysconfdir"/rc.d/init.d/functions
+
+URIS=default
+ON_BOOT=start
+ON_SHUTDOWN=suspend
+SHUTDOWN_TIMEOUT=0
+
+test -f "$sysconfdir"/sysconfig/libvirt-guests && . "$sysconfdir"/sysconfig/libvirt-guests
+
+LISTFILE="$localstatedir"/lib/libvirt/libvirt-guests
+VAR_SUBSYS_LIBVIRT_GUESTS="$localstatedir"/lock/subsys/libvirt-guests
+
+RETVAL=0
+
+retval() {
+ "$@"
+ if [ $? -ne 0 ]; then
+ RETVAL=1
+ return 1
+ else
+ return 0
+ fi
+}
+
+run_virsh() {
+ uri=$1
+ shift
+
+ if [ "x$uri" = xdefault ]; then
+ conn=
+ else
+ conn="-c $uri"
+ fi
+
+ virsh $conn "$@" </dev/null
+}
+
+run_virsh_c() {
+ ( export LC_ALL=C; run_virsh "$@" )
+}
+
+list_guests() {
+ uri=$1
+
+ list=$(run_virsh_c $uri list)
+ if [ $? -ne 0 ]; then
+ RETVAL=1
+ return 1
+ fi
+
+ uuids=
+ for id in $(echo "$list" | awk 'NR > 2 {print $1}'); do
+ uuid=$(run_virsh_c $uri dominfo $id | awk '/^UUID:/{print $2}')
+ if [ -z "$uuid" ]; then
+ RETVAL=1
+ return 1
+ fi
+ uuids="$uuids $uuid"
+ done
+
+ echo $uuids
+}
+
+guest_name() {
+ uri=$1
+ uuid=$2
+
+ name=$(run_virsh_c $uri dominfo $uuid 2>/dev/null | \
+ awk '/^Name:/{print $2}')
+ [ -n "$name" ] || name=$uuid
+
+ echo "$name"
+}
+
+guest_is_on() {
+ uri=$1
+ uuid=$2
+
+ guest_running=false
+ info=$(run_virsh_c $uri dominfo $uuid)
+ if [ $? -ne 0 ]; then
+ RETVAL=1
+ return 1
+ fi
+
+ id=$(echo "$info" | awk '/^Id:/{print $2}')
+
+ [ -n "$id" ] && [ "x$id" != x- ] && guest_running=true
+ return 0
+}
+
+started() {
+ touch "$VAR_SUBSYS_LIBVIRT_GUESTS"
+}
+
+start() {
+ [ -f "$LISTFILE" ] || { started; return 0; }
+
+ if [ "x$ON_BOOT" != xstart ]; then
+ echo $"libvirt-guests is configured not to start any guests on boot"
+ rm -f "$LISTFILE"
+ started
+ return 0
+ fi
+
+ while read uri list; do
+ configured=false
+ for confuri in $URIS; do
+ if [ $confuri = $uri ]; then
+ configured=true
+ break
+ fi
+ done
+ if ! $configured; then
+ echo $"Ignoring guests on $uri URI"
+ continue
+ fi
+
+ echo $"Resuming guests on $uri URI..."
+ for guest in $list; do
+ name=$(guest_name $uri $guest)
+ echo -n $"Resuming guest $name: "
+ if guest_is_on $uri $guest; then
+ if $guest_running; then
+ echo $"already active"
+ else
+ retval run_virsh $uri start "$name" >/dev/null && \
+ echo $"done"
+ fi
+ fi
+ done
+ done <"$LISTFILE"
+
+ rm -f "$LISTFILE"
+ started
+}
+
+suspend_guest()
+{
+ uri=$1
+ guest=$2
+
+ name=$(guest_name $uri $guest)
+ label=$"Suspending $name: "
+ echo -n "$label"
+ run_virsh $uri managedsave $guest >/dev/null &
+ virsh_pid=$!
+ while true; do
+ sleep 1
+ kill -0 $virsh_pid >&/dev/null || break
+ progress=$(run_virsh_c $uri domjobinfo $guest 2>/dev/null | \
+ awk '/^Data processed:/{print $3, $4}')
+ if [ -n "$progress" ]; then
+ printf '\r%s%12s ' "$label" "$progress"
+ else
+ printf '\r%s%-12s ' "$label" "..."
+ fi
+ done
+ retval wait $virsh_pid && printf '\r%s%-12s\n' "$label" $"done"
+}
+
+shutdown_guest()
+{
+ uri=$1
+ guest=$2
+
+ name=$(guest_name $uri $guest)
+ label=$"Shutting down $name: "
+ echo -n "$label"
+ retval run_virsh $uri shutdown $guest >/dev/null || return
+ timeout=$SHUTDOWN_TIMEOUT
+ while [ $timeout -gt 0 ]; do
+ sleep 1
+ timeout=$[timeout - 1]
+ guest_is_on $uri $guest || return
+ $guest_running || break
+ printf '\r%s%-12d ' "$label" $timeout
+ done
+
+ if guest_is_on $uri $guest; then
+ if $guest_running; then
+ printf '\r%s%-12s\n' "$label" $"failed to shutdown in time"
+ else
+ printf '\r%s%-12s\n' "$label" $"done"
+ fi
+ fi
+}
+
+stop() {
+ # last stop was not followed by start
+ [ -f "$LISTFILE" ] && return 0
+
+ suspending=true
+ if [ "x$ON_SHUTDOWN" = xshutdown ]; then
+ suspending=false
+ if [ $SHUTDOWN_TIMEOUT -le 0 ]; then
+ echo $"Shutdown action requested but SHUTDOWN_TIMEOUT was not set"
+ RETVAL=6
+ return
+ fi
+ fi
+
+ : >"$LISTFILE"
+ for uri in $URIS; do
+ echo -n $"Running guests on $uri URI: "
+
+ if [ "x$uri" = xdefault ] && [ ! -x "$libvirtd" ]; then
+ echo $"libvirtd not installed; skipping this URI."
+ continue
+ fi
+
+ list=$(list_guests $uri)
+ if [ $? -eq 0 ]; then
+ empty=true
+ for uuid in $list; do
+ $empty || printf ", "
+ echo -n $(guest_name $uri $uuid)
+ empty=false
+ done
+ if $empty; then
+ echo $"no running guests."
+ else
+ echo
+ echo $uri $list >>"$LISTFILE"
+ fi
+ fi
+ done
+
+ while read uri list; do
+ if $suspending; then
+ echo $"Suspending guests on $uri URI..."
+ else
+ echo $"Shutting down guests on $uri URI..."
+ fi
+
+ for guest in $list; do
+ if $suspending; then
+ suspend_guest $uri $guest
+ else
+ shutdown_guest $uri $guest
+ fi
+ done
+ done <"$LISTFILE"
+
+ rm -f "$VAR_SUBSYS_LIBVIRT_GUESTS"
+}
+
+gueststatus() {
+ for uri in $URIS; do
+ echo "* $uri URI:"
+ retval run_virsh $uri list || echo
+ done
+}
+
+# rh_status
+# Display current status: whether saved state exists, and whether start
+# has been executed. We cannot use status() from the functions library,
+# since there is no external daemon process matching this init script.
+rh_status() {
+ if [ -f "$LISTFILE" ]; then
+ echo $"stopped, with saved guests"
+ RETVAL=3
+ else
+ if [ -f "$VAR_SUBSYS_LIBVIRT_GUESTS" ]; then
+ echo $"started"
+ else
+ echo $"stopped, with no saved guests"
+ fi
+ RETVAL=0
+ fi
+}
+
+# usage [val]
+# Display usage string, then exit with VAL (defaults to 2).
+usage() {
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|gueststatus|shutdown}"
+ exit ${1-2}
+}
+
+# See how we were called.
+if test $# != 1; then
+ usage
+fi
+case "$1" in
+ --help)
+ usage 0
+ ;;
+ start|stop|gueststatus)
+ $1
+ ;;
+ restart)
+ stop && start
+ ;;
+ condrestart|try-restart)
+ [ -f "$VAR_SUBSYS_LIBVIRT_GUESTS" ] && stop && start
+ ;;
+ reload|force-reload)
+ # Nothing to do; we reread configuration on each invocation
+ ;;
+ status)
+ rh_status
+ ;;
+ shutdown)
+ ON_SHUTDOWN=shutdown
+ stop
+ ;;
+ *)
+ usage
+ ;;
+esac
+exit $RETVAL
diff --git a/tools/libvirt-guests.sysconf b/tools/libvirt-guests.sysconf
new file mode 100644
index 0000000..cd58728
--- /dev/null
+++ b/tools/libvirt-guests.sysconf
@@ -0,0 +1,24 @@
+# URIs to check for running guests
+# example: URIS='default xen:/// vbox+tcp://host/system lxc:///'
+#URIS=default
+
+# action taken on host boot
+# - start all guests which were running on shutdown are started on boot
+# regardless on their autostart settings
+# - ignore libvirt-guests init script won't start any guest on boot, however,
+# guests marked as autostart will still be automatically started by
+# libvirtd
+#ON_BOOT=start
+
+# action taken on host shutdown
+# - suspend all running guests are suspended using virsh managedsave
+# - shutdown all running guests are asked to shutdown. Please be careful with
+# this settings since there is no way to distinguish between a
+# guest which is stuck or ignores shutdown requests and a guest
+# which just needs a long time to shutdown. When setting
+# ON_SHUTDOWN=shutdown, you must also set SHUTDOWN_TIMEOUT to a
+# value suitable for your guests.
+#ON_SHUTDOWN=suspend
+
+# number of seconds we're willing to wait for a guest to shut down
+#SHUTDOWN_TIMEOUT=0
--
1.7.2.2
14 years, 3 months