[libvirt] [PATCH v3] Improve SCSI volume key generation
by Daniel P. Berrange
The SCSI volumes get a better 'key' field based on the fully
qualified volume path. All SCSI volumes have a unique serial
available in hardware which can be obtained by sending a
suitable SCSI command. Call out to udev's 'scsi_id' command
to fetch this value
In v3:
- Use virCommandSetOutputBuffer/virCommandRun instead
of VIR_FDOPEN
- Skip serial if it matches empty string
* src/storage/storage_backend_scsi.c: Improve volume key
field value stability and uniqueness
---
src/storage/storage_backend_scsi.c | 45 ++++++++++++++++++++++++++++++++---
1 files changed, 41 insertions(+), 4 deletions(-)
diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c
index d880d65..da34547 100644
--- a/src/storage/storage_backend_scsi.c
+++ b/src/storage/storage_backend_scsi.c
@@ -33,6 +33,7 @@
#include "memory.h"
#include "logging.h"
#include "files.h"
+#include "command.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
@@ -160,6 +161,45 @@ cleanup:
return ret;
}
+
+static char *
+virStorageBackendSCSISerial(const char *dev)
+{
+ char *serial = NULL;
+#ifdef HAVE_UDEV
+ virCommandPtr cmd = virCommandNewArgList(
+ "/lib/udev/scsi_id",
+ "--replace-whitespace",
+ "--whitelisted",
+ "--device", dev,
+ NULL
+ );
+
+ /* Run the program and capture its output */
+ virCommandSetOutputBuffer(cmd, &serial);
+ if (virCommandRun(cmd, NULL) < 0)
+ goto cleanup;
+#endif
+
+ if (serial && STRNEQ(serial, "")) {
+ char *nl = strchr(serial, '\n');
+ if (nl)
+ *nl = '\0';
+ } else {
+ VIR_FREE(serial);
+ if (!(serial = strdup(dev)))
+ virReportOOMError();
+ }
+
+#ifdef HAVE_UDEV
+cleanup:
+ virCommandFree(cmd);
+#endif
+
+ return serial;
+}
+
+
static int
virStorageBackendSCSINewLun(virStoragePoolObjPtr pool,
uint32_t host ATTRIBUTE_UNUSED,
@@ -233,10 +273,7 @@ virStorageBackendSCSINewLun(virStoragePoolObjPtr pool,
goto free_vol;
}
- /* XXX should use logical unit's UUID instead */
- vol->key = strdup(vol->target.path);
- if (vol->key == NULL) {
- virReportOOMError();
+ if (!(vol->key = virStorageBackendSCSISerial(vol->target.path))) {
retval = -1;
goto free_vol;
}
--
1.7.4
13 years, 8 months
[libvirt] [PATCH] qemu: Ignore unusable binaries
by Jiri Denemark
When initializing qemu guest capabilities, we should ignore qemu
binaries that we are not able to extract version/help info from since
they will be unusable for creating domains anyway. Ignoring them is also
much better than letting initialization of qemu driver fail.
---
src/qemu/qemu_capabilities.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index f86e7f5..63486cc 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -490,6 +490,12 @@ qemuCapsInitGuest(virCapsPtr caps,
if (!binary)
return 0;
+ /* Ignore binary if extracting version info fails */
+ if (qemuCapsExtractVersionInfo(binary, info->arch, NULL, &qemuCaps) < 0) {
+ ret = 0;
+ goto cleanup;
+ }
+
if (stat(binary, &st) == 0) {
binary_mtime = st.st_mtime;
} else {
@@ -554,9 +560,8 @@ qemuCapsInitGuest(virCapsPtr caps,
!virCapabilitiesAddGuestFeature(guest, "cpuselection", 1, 0))
goto error;
- if (qemuCapsExtractVersionInfo(binary, info->arch, NULL, &qemuCaps) < 0 ||
- (qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX) &&
- !virCapabilitiesAddGuestFeature(guest, "deviceboot", 1, 0)))
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX) &&
+ !virCapabilitiesAddGuestFeature(guest, "deviceboot", 1, 0))
goto error;
if (hvm) {
--
1.7.4.1
13 years, 8 months
[libvirt] [PATCH] qemu: Rewrite LOOKUP_PTYS macro into a function
by Jiri Denemark
The macro is huge and gives us nothing but headache when maintaining it.
---
The reason for this patch is not that I'm going to modify anything in
the code. It's that I was working in the area and noticed this huge
macro.
src/qemu/qemu_process.c | 102 ++++++++++++++++++++++++++++-------------------
1 files changed, 61 insertions(+), 41 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 90fcea0..53a42a5 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -895,51 +895,71 @@ qemuProcessExtractTTYPath(const char *haystack,
}
static int
+qemuProcessLookupPTYs(virDomainChrDefPtr *devices,
+ int count,
+ const char *prefix,
+ virHashTablePtr paths)
+{
+ int i;
+
+ for (i = 0 ; i < count ; i++) {
+ virDomainChrDefPtr chr = devices[i];
+ if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) {
+ char id[16];
+ const char *path;
+
+ if (snprintf(id, sizeof(id), "%s%d", prefix, i) >= sizeof(id))
+ return -1;
+
+ path = (const char *) virHashLookup(paths, id);
+ if (path == NULL) {
+ if (chr->source.data.file.path == NULL) {
+ /* neither the log output nor 'info chardev' had a
+ * pty path for this chardev, report an error
+ */
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("no assigned pty for device %s"), id);
+ return -1;
+ } else {
+ /* 'info chardev' had no pty path for this chardev,
+ * but the log output had, so we're fine
+ */
+ continue;
+ }
+ }
+
+ VIR_FREE(chr->source.data.file.path);
+ chr->source.data.file.path = strdup(path);
+
+ if (chr->source.data.file.path == NULL) {
+ virReportOOMError();
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
qemuProcessFindCharDevicePTYsMonitor(virDomainObjPtr vm,
virHashTablePtr paths)
{
- int i;
+ if (qemuProcessLookupPTYs(vm->def->serials, vm->def->nserials,
+ "serial", paths) < 0)
+ return -1;
+
+ if (qemuProcessLookupPTYs(vm->def->parallels, vm->def->nparallels,
+ "parallel", paths) < 0)
+ return -1;
-#define LOOKUP_PTYS(array, arraylen, idprefix) \
- for (i = 0 ; i < (arraylen) ; i++) { \
- virDomainChrDefPtr chr = (array)[i]; \
- if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) { \
- char id[16]; \
- \
- if (snprintf(id, sizeof(id), idprefix "%i", i) >= sizeof(id)) \
- return -1; \
- \
- const char *path = (const char *) virHashLookup(paths, id); \
- if (path == NULL) { \
- if (chr->source.data.file.path == NULL) { \
- /* neither the log output nor 'info chardev' had a */ \
- /* pty path for this chardev, report an error */ \
- qemuReportError(VIR_ERR_INTERNAL_ERROR, \
- _("no assigned pty for device %s"), id); \
- return -1; \
- } else { \
- /* 'info chardev' had no pty path for this chardev, */\
- /* but the log output had, so we're fine */ \
- continue; \
- } \
- } \
- \
- VIR_FREE(chr->source.data.file.path); \
- chr->source.data.file.path = strdup(path); \
- \
- if (chr->source.data.file.path == NULL) { \
- virReportOOMError(); \
- return -1; \
- } \
- } \
- }
-
- LOOKUP_PTYS(vm->def->serials, vm->def->nserials, "serial");
- LOOKUP_PTYS(vm->def->parallels, vm->def->nparallels, "parallel");
- LOOKUP_PTYS(vm->def->channels, vm->def->nchannels, "channel");
- if (vm->def->console)
- LOOKUP_PTYS(&vm->def->console, 1, "console");
-#undef LOOKUP_PTYS
+ if (qemuProcessLookupPTYs(vm->def->channels, vm->def->nchannels,
+ "channel", paths) < 0)
+ return -1;
+
+ if (vm->def->console &&
+ qemuProcessLookupPTYs(&vm->def->console, 1, "console", paths) < 0)
+ return -1;
return 0;
}
--
1.7.4.1
13 years, 8 months
[libvirt] [PATCH] virsh: Increase device-detach intelligence
by Michal Privoznik
Up to now users have to give a full XML description on input when
device-detaching. If they omited something it lead to unclear
error messages (like generated MAC wasn't found, etc.).
With this patch users can specify only those information which
specify one device sufficiently precise. Remaining information is
completed from domain.
---
tools/virsh.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 245 insertions(+), 15 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 50ca50f..95d27f7 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -8702,6 +8702,224 @@ cmdAttachDevice(vshControl *ctl, const vshCmd *cmd)
return TRUE;
}
+/**
+ * Check if n1 is superset of n2, meaning n1 contains all elements and
+ * attributes as n2 at lest. Including children.
+ * @n1 first node
+ * @n2 second node
+ * return 1 in case n1 covers n2, 0 otherwise.
+ */
+static int
+vshNodeIsSuperset(xmlNodePtr n1, xmlNodePtr n2) {
+ xmlNodePtr child1, child2;
+ xmlAttrPtr attr1, attr2;
+ int found;
+
+ if (!n1 && !n2)
+ return 1;
+
+ if (!n1 || !n2)
+ return 0;
+
+ if (!xmlStrEqual(n1->name, n2->name))
+ return 0;
+
+ attr2 = n2->properties;
+ while (attr2) {
+ if (attr2->type == XML_ATTRIBUTE_NODE) {
+ attr1 = n1->properties;
+ found = 0;
+ while (attr1) {
+ if (xmlStrEqual(attr1->name, attr2->name)) {
+ found = 1;
+ break;
+ }
+ attr1 = attr1->next;
+ }
+ if (!found)
+ return 0;
+ if (!xmlStrEqual(BAD_CAST virXMLPropString(n1, (const char *) attr1->name),
+ BAD_CAST virXMLPropString(n2, (const char *) attr2->name)))
+ return 0;
+ }
+ attr2 = attr2->next;
+ }
+
+ child2 = n2->children;
+ while (child2) {
+ if (child2->type == XML_ELEMENT_NODE) {
+ child1 = n1->children;
+ found = 0;
+ while (child1) {
+ if (child1->type == XML_ELEMENT_NODE &&
+ xmlStrEqual(child1->name, child2->name)) {
+ found = 1;
+ break;
+ }
+ child1 = child1->next;
+ }
+ if (!found)
+ return 0;
+ if (!vshNodeIsSuperset(child1, child2))
+ return 0;
+ }
+ child2 = child2->next;
+ }
+
+ return 1;
+}
+
+/**
+ * To given domain and (probably incomplete) device XML specification try to
+ * find such device in domain and complete missing parts. This is however
+ * possible when given device XML is sufficiently precise so it addresses only
+ * one device.
+ * @ctl vshControl for error messages printing
+ * @dom domain
+ * @oldXML device XML before
+ * @newXML and after completion
+ * Returns -2 when no such device exists in domain, -3 when given XML selects many
+ * (is too ambiguous), 0 in case of success. Otherwise returns -1. @newXML
+ * is touched only in case of success.
+ */
+static int
+vshCompleteXMLFromDomain(vshControl *ctl, virDomainPtr dom, char *oldXML,
+ char **newXML) {
+ int funcRet = -1;
+ char *domXML = NULL;
+ xmlDocPtr domDoc = NULL, devDoc = NULL;
+ xmlNodePtr node = NULL;
+ xmlXPathContextPtr domCtxt = NULL, devCtxt = NULL;
+ xmlNodePtr *devices = NULL;
+ xmlSaveCtxtPtr sctxt = NULL;
+ int devices_size;
+ char *xpath;
+ xmlBufferPtr buf = NULL;
+
+ if (!(domXML = virDomainGetXMLDesc(dom, 0))) {
+ vshError(ctl, _("couldn't get XML description of domain %s"),
+ virDomainGetName(dom));
+ goto error;
+ }
+
+ if (!(domDoc = xmlReadDoc(BAD_CAST domXML, "domain.xml", NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
+ vshError(ctl, "%s", _("could not parse domain XML"));
+ goto error;
+ }
+
+ if (!(devDoc = xmlReadDoc(BAD_CAST oldXML, "device.xml", NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
+ vshError(ctl, "%s", _("could not parse device XML"));
+ goto error;
+ }
+
+ node = xmlDocGetRootElement(domDoc);
+ if (!node) {
+ vshError(ctl, "%s", _("failed to get domain root element"));
+ goto error;
+ }
+
+ domCtxt = xmlXPathNewContext(domDoc);
+ if (!domCtxt) {
+ vshError(ctl, "%s", _("failed to create context"));
+ goto error;
+ }
+ domCtxt->node = node;
+
+ node = xmlDocGetRootElement(devDoc);
+ if (!node) {
+ vshError(ctl, "%s", _("failed to get device root element"));
+ goto error;
+ }
+
+ devCtxt = xmlXPathNewContext(devDoc);
+ if (!devCtxt) {
+ vshError(ctl, "%s", _("failed to create context"));
+ goto error;
+ }
+ devCtxt->node = node;
+
+ buf = xmlBufferCreate();
+ if (!buf) {
+ vshError(ctl, "%s", _("out of memory"));
+ goto error;
+ }
+
+ xmlBufferCat(buf, BAD_CAST "/domain/devices/");
+ xmlBufferCat(buf, node->name);
+ xpath = (char *) xmlBufferContent(buf);
+ /* we get all possible devices */
+ devices_size = virXPathNodeSet(xpath, domCtxt, &devices);
+ xmlBufferEmpty(buf);
+
+ if (devices_size < 0) {
+ /* error */
+ vshError(ctl, "%s", _("error when selecting nodes"));
+ goto error;
+ } else if (devices_size < 1) {
+ /* no such device */
+ funcRet = -2;
+ goto error;
+ }
+
+ /* and refine */
+ int i = 0;
+ while (i < devices_size) {
+ if (!vshNodeIsSuperset(devices[i], node)) {
+ if (devices_size == 1) {
+ VIR_FREE(devices);
+ devices_size = 0;
+ } else {
+ memmove(devices + i, devices + i + 1,
+ sizeof(*devices) * (devices_size-i-1));
+ devices_size--;
+ if (VIR_REALLOC_N(devices, devices_size) < 0) {
+ /* ignore, harmless */
+ }
+ }
+ } else {
+ i++;
+ }
+ }
+
+ if (!devices_size) {
+ /* no such device */
+ funcRet = -2;
+ goto error;
+ } else if (devices_size > 1) {
+ /* ambiguous */
+ funcRet = -3;
+ goto error;
+ }
+
+ if (newXML) {
+ sctxt = xmlSaveToBuffer(buf, NULL, 0);
+ if (!sctxt) {
+ vshError(ctl, "%s", _("failed to create document saving context"));
+ goto error;
+ }
+
+ xmlSaveTree(sctxt, devices[0]);
+ xmlSaveClose(sctxt);
+ *newXML = (char *) xmlBufferContent(buf);
+ buf->content = NULL;
+ }
+
+ funcRet = 0;
+
+error:
+ xmlBufferFree(buf);
+ VIR_FREE(devices);
+ xmlXPathFreeContext(devCtxt);
+ xmlXPathFreeContext(domCtxt);
+ xmlFreeDoc(devDoc);
+ xmlFreeDoc(domDoc);
+ VIR_FREE(domXML);
+ return funcRet;
+}
/*
* "detach-device" command
@@ -8724,7 +8942,7 @@ cmdDetachDevice(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
const char *from = NULL;
- char *buffer;
+ char *buffer = NULL, *new_buffer = NULL;
int ret = TRUE;
unsigned int flags;
@@ -8734,37 +8952,49 @@ cmdDetachDevice(vshControl *ctl, const vshCmd *cmd)
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
- if (vshCommandOptString(cmd, "file", &from) <= 0) {
- virDomainFree(dom);
- return FALSE;
- }
+ if (vshCommandOptString(cmd, "file", &from) <= 0)
+ goto error;
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
virshReportError(ctl);
- virDomainFree(dom);
- return FALSE;
+ goto error;
+ }
+
+ ret = vshCompleteXMLFromDomain(ctl, dom, buffer, &new_buffer);
+ if (ret < 0) {
+ if (ret == -2) {
+ vshError(ctl, _("no such device in %s"), virDomainGetName(dom));
+ } else if (ret == -3) {
+ vshError(ctl, "%s", _("given XML selects too many devices. "
+ "Please, be more specific"));
+ }
+ ret = FALSE;
+ goto error;
}
if (vshCommandOptBool(cmd, "persistent")) {
flags = VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
if (virDomainIsActive(dom) == 1)
flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
- ret = virDomainDetachDeviceFlags(dom, buffer, flags);
+ ret = virDomainDetachDeviceFlags(dom, new_buffer, flags);
} else {
- ret = virDomainDetachDevice(dom, buffer);
+ ret = virDomainDetachDevice(dom, new_buffer);
}
- VIR_FREE(buffer);
if (ret < 0) {
vshError(ctl, _("Failed to detach device from %s"), from);
- virDomainFree(dom);
- return FALSE;
- } else {
- vshPrint(ctl, "%s", _("Device detached successfully\n"));
+ ret = FALSE;
+ goto error;
}
+ vshPrint(ctl, "%s", _("Device detached successfully\n"));
+ ret = TRUE;
+
+error:
+ VIR_FREE(new_buffer);
+ VIR_FREE(buffer);
virDomainFree(dom);
- return TRUE;
+ return ret;
}
--
1.7.4
13 years, 8 months
[libvirt] [PATCH] vmx: Use case-insensitive compare functions for all content
by Matthias Bolte
---
src/vmx/vmx.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
index 9f4d5fb..9a482ef 100644
--- a/src/vmx/vmx.c
+++ b/src/vmx/vmx.c
@@ -730,7 +730,7 @@ virVMXGetConfigLong(virConfPtr conf, const char *name, long long *number,
}
}
- if (STREQ(value->str, "unlimited")) {
+ if (STRCASEEQ(value->str, "unlimited")) {
*number = -1;
} else if (virStrToLong_ll(value->str, NULL, 10, number) < 0) {
VMX_ERROR(VIR_ERR_INTERNAL_ERROR,
@@ -1385,7 +1385,7 @@ virVMXParseConfig(virVMXContext *ctx, virCapsPtr caps, const char *vmx)
goto cleanup;
}
- if (sched_cpu_affinity != NULL && STRNEQ(sched_cpu_affinity, "all")) {
+ if (sched_cpu_affinity != NULL && STRCASENEQ(sched_cpu_affinity, "all")) {
const char *current = sched_cpu_affinity;
int number, count = 0;
@@ -2107,7 +2107,7 @@ virVMXParseDisk(virVMXContext *ctx, virCapsPtr caps, virConfPtr conf,
goto cleanup;
}
} else if (virFileHasSuffix(fileName, ".iso") ||
- STREQ(deviceType, "atapi-cdrom")) {
+ STRCASEEQ(deviceType, "atapi-cdrom")) {
/*
* This function was called in order to parse a harddisk device,
* but .iso files and 'atapi-cdrom' devices are for CDROM devices
@@ -2146,7 +2146,7 @@ virVMXParseDisk(virVMXContext *ctx, virCapsPtr caps, virConfPtr conf,
* handle it.
*/
goto ignore;
- } else if (STREQ(deviceType, "atapi-cdrom")) {
+ } else if (STRCASEEQ(deviceType, "atapi-cdrom")) {
(*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
(*def)->src = fileName;
@@ -2174,7 +2174,7 @@ virVMXParseDisk(virVMXContext *ctx, virCapsPtr caps, virConfPtr conf,
if ((*def)->src == NULL) {
goto cleanup;
}
- } else if (fileType != NULL && STREQ(fileType, "device")) {
+ } else if (fileType != NULL && STRCASEEQ(fileType, "device")) {
(*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
(*def)->src = fileName;
--
1.7.0.4
13 years, 8 months
[libvirt] [PATCH] vmx: Support persistent CPU shares
by Matthias Bolte
---
src/vmx/vmx.c | 43 ++++++++++++++++++++++
tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx | 2 +-
tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml | 3 ++
tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml | 3 ++
tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx | 2 +-
tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml | 3 ++
tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml | 3 ++
tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml | 3 ++
tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx | 1 +
tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml | 3 ++
tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx | 1 +
tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml | 3 ++
tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx | 1 +
tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml | 3 ++
14 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
index 9a482ef..b0d3218 100644
--- a/src/vmx/vmx.c
+++ b/src/vmx/vmx.c
@@ -55,6 +55,8 @@ def->mem.cur_balloon = <value kilobyte> <=> sched.mem.max = "<value megabyt
def->mem.min_guarantee = <value kilobyte> <=> sched.mem.minsize = "<value megabyte>" # defaults to 0
def->maxvcpus = <value> <=> numvcpus = "<value>" # must be 1 or a multiple of 2, defaults to 1
def->cpumask = <uint list> <=> sched.cpu.affinity = "<uint list>"
+def->cputune.shares = <value> <=> sched.cpu.shares = "<value>" # with handling for special values
+ # "high", "normal", "low"
@@ -1200,6 +1202,7 @@ virVMXParseConfig(virVMXContext *ctx, virCapsPtr caps, const char *vmx)
long long sched_mem_minsize = 0;
long long numvcpus = 0;
char *sched_cpu_affinity = NULL;
+ char *sched_cpu_shares = NULL;
char *guestOS = NULL;
bool smbios_reflecthost = false;
int controller;
@@ -1449,6 +1452,30 @@ virVMXParseConfig(virVMXContext *ctx, virCapsPtr caps, const char *vmx)
}
}
+ /* vmx:sched.cpu.shares -> def:cputune.shares */
+ if (virVMXGetConfigString(conf, "sched.cpu.shares", &sched_cpu_shares,
+ true) < 0) {
+ goto cleanup;
+ }
+
+ if (sched_cpu_shares != NULL) {
+ /* See http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/v... */
+ if (STRCASEEQ(sched_cpu_shares, "low")) {
+ def->cputune.shares = def->vcpus * 500;
+ } else if (STRCASEEQ(sched_cpu_shares, "normal")) {
+ def->cputune.shares = def->vcpus * 1000;
+ } else if (STRCASEEQ(sched_cpu_shares, "high")) {
+ def->cputune.shares = def->vcpus * 2000;
+ } else if (virStrToLong_ul(sched_cpu_shares, NULL, 10,
+ &def->cputune.shares) < 0) {
+ VMX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Expecting VMX entry 'sched.cpu.shares' to be an "
+ "unsigned integer or 'low', 'normal' or 'high' but "
+ "found '%s'"), sched_cpu_shares);
+ goto cleanup;
+ }
+ }
+
/* def:lifecycle */
def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
@@ -1715,6 +1742,7 @@ virVMXParseConfig(virVMXContext *ctx, virCapsPtr caps, const char *vmx)
virConfFree(conf);
VIR_FREE(encoding);
VIR_FREE(sched_cpu_affinity);
+ VIR_FREE(sched_cpu_shares);
VIR_FREE(guestOS);
return def;
@@ -2998,6 +3026,21 @@ virVMXFormatConfig(virVMXContext *ctx, virCapsPtr caps, virDomainDefPtr def,
virBufferAddLit(&buffer, "\"\n");
}
+ /* def:cputune.shares -> vmx:sched.cpu.shares */
+ if (def->cputune.shares > 0) {
+ /* See http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/v... */
+ if (def->cputune.shares == def->vcpus * 500) {
+ virBufferAddLit(&buffer, "sched.cpu.shares = \"low\"\n");
+ } else if (def->cputune.shares == def->vcpus * 1000) {
+ virBufferAddLit(&buffer, "sched.cpu.shares = \"normal\"\n");
+ } else if (def->cputune.shares == def->vcpus * 2000) {
+ virBufferAddLit(&buffer, "sched.cpu.shares = \"high\"\n");
+ } else {
+ virBufferVSprintf(&buffer, "sched.cpu.shares = \"%lu\"\n",
+ def->cputune.shares);
+ }
+ }
+
/* def:graphics */
for (i = 0; i < def->ngraphics; ++i) {
switch (def->graphics[i]->type) {
diff --git a/tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx b/tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx
index bd36cf8..8641c5c 100644
--- a/tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx
+++ b/tests/vmx2xmldata/vmx2xml-case-insensitive-1.vmx
@@ -35,7 +35,7 @@ UUID.BIOS = "50 11 5E 16 9B DC 49 D7-F1 71 53 C4 D7 F9 17 10"
SNAPSHOT.ACTION = "KEEP"
SCHED.CPU.MIN = "0"
SCHED.CPU.UNITS = "MHZ"
-SCHED.CPU.SHARES = "NORMAL"
+SCHED.CPU.SHARES = "4223"
SCHED.MEM.MINSIZE = "0"
SCHED.MEM.SHARES = "NORMAL"
TOOLSCRIPTS.AFTERPOWERON = "TRUE"
diff --git a/tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml b/tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml
index 7a5ff5b..ef6edd8 100644
--- a/tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml
+++ b/tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml
@@ -4,6 +4,9 @@
<memory>1048576</memory>
<currentMemory>1048576</currentMemory>
<vcpu>1</vcpu>
+ <cputune>
+ <shares>4223</shares>
+ </cputune>
<os>
<type arch='i686'>hvm</type>
</os>
diff --git a/tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml b/tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml
index 18d6461..02771b9 100644
--- a/tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml
+++ b/tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml
@@ -4,6 +4,9 @@
<memory>1048576</memory>
<currentMemory>1048576</currentMemory>
<vcpu>1</vcpu>
+ <cputune>
+ <shares>1000</shares>
+ </cputune>
<os>
<type arch='i686'>hvm</type>
</os>
diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx
index 4392062..78741ae 100644
--- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx
+++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.vmx
@@ -36,7 +36,7 @@ uuid.bios = "50 11 5e 16 9b dc 49 d7-f1 71 53 c4 d7 f9 17 10"
snapshot.action = "keep"
sched.cpu.min = "0"
sched.cpu.units = "mhz"
-sched.cpu.shares = "normal"
+sched.cpu.shares = "low"
sched.mem.minsize = "0"
sched.mem.shares = "normal"
toolScripts.afterPowerOn = "true"
diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml
index 5e67e74..e8f9307 100644
--- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml
+++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml
@@ -4,6 +4,9 @@
<memory>1048576</memory>
<currentMemory>1048576</currentMemory>
<vcpu>1</vcpu>
+ <cputune>
+ <shares>500</shares>
+ </cputune>
<os>
<type arch='i686'>hvm</type>
</os>
diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml
index 419df51..2824d66 100644
--- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml
+++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml
@@ -4,6 +4,9 @@
<memory>524288</memory>
<currentMemory>524288</currentMemory>
<vcpu>1</vcpu>
+ <cputune>
+ <shares>1000</shares>
+ </cputune>
<os>
<type arch='i686'>hvm</type>
</os>
diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml
index 0040163..6f0a9d1 100644
--- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml
+++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml
@@ -8,6 +8,9 @@
<min_guarantee>262144</min_guarantee>
</memtune>
<vcpu>2</vcpu>
+ <cputune>
+ <shares>2000</shares>
+ </cputune>
<os>
<type arch='x86_64'>hvm</type>
</os>
diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx
index e72ca80..9059197 100644
--- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx
+++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.vmx
@@ -6,6 +6,7 @@ uuid.bios = "50 11 5e 16 9b dc 49 d7-f1 71 53 c4 d7 f9 17 10"
displayName = "Fedora11"
memsize = "1024"
numvcpus = "1"
+sched.cpu.shares = "low"
scsi0.present = "true"
scsi0.virtualDev = "lsilogic"
scsi0:0.present = "true"
diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml
index 3f4ff88..ea59778 100644
--- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml
+++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-1.xml
@@ -4,6 +4,9 @@
<memory>1048576</memory>
<currentMemory>1048576</currentMemory>
<vcpu>1</vcpu>
+ <cputune>
+ <shares>500</shares>
+ </cputune>
<os>
<type>hvm</type>
</os>
diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx
index 627fcfb..504997f 100644
--- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx
+++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.vmx
@@ -6,6 +6,7 @@ uuid.bios = "56 4d 9b ef ac d9 b4 e0-c8 f0 ae a8 b9 10 35 15"
displayName = "virtMonServ1"
memsize = "512"
numvcpus = "1"
+sched.cpu.shares = "normal"
scsi0.present = "true"
scsi0.virtualDev = "lsilogic"
scsi0:0.present = "true"
diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml
index 078753a..443aacd 100644
--- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml
+++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-4.xml
@@ -4,6 +4,9 @@
<memory>524288</memory>
<currentMemory>524288</currentMemory>
<vcpu>1</vcpu>
+ <cputune>
+ <shares>1000</shares>
+ </cputune>
<os>
<type>hvm</type>
</os>
diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx
index cc2485f..2e3b856 100644
--- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx
+++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx
@@ -8,6 +8,7 @@ annotation = "Centos 5.5 64bit Server"
memsize = "2048"
sched.mem.minsize = "256"
numvcpus = "2"
+sched.cpu.shares = "normal"
scsi0.present = "true"
scsi0.virtualDev = "lsilogic"
scsi0:0.present = "true"
diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml
index d55bf6b..f28c15e 100644
--- a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml
+++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml
@@ -8,6 +8,9 @@
<min_guarantee>262144</min_guarantee>
</memtune>
<vcpu>2</vcpu>
+ <cputune>
+ <shares>2000</shares>
+ </cputune>
<os>
<type arch='x86_64'>hvm</type>
</os>
--
1.7.0.4
13 years, 8 months
[libvirt] [PATCH] Add autostart support to libxl driver
by Markus Groß
This patch is rebased against the patchset from here:
https://www.redhat.com/archives/libvir-list/2011-March/msg01260.html
The domainSetAutostart function is nearly identical to the one from qemu.
---
src/libxl/libxl_driver.c | 137 ++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 131 insertions(+), 6 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 3409340..9d882ba 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -176,6 +176,29 @@ libxlDomainObjUnref(void *data)
ignore_value(virDomainObjUnref(vm));
}
+static void
+libxlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ libxlDriverPrivatePtr driver = opaque;
+ virDomainObjPtr vm = payload;
+ virErrorPtr err;
+
+ virDomainObjLock(vm);
+ virResetLastError();
+
+ if (vm->autostart && !virDomainObjIsActive(vm) &&
+ libxlVmStart(driver, vm, false) < 0) {
+ err = virGetLastError();
+ VIR_ERROR(_("Failed to autostart VM '%s': %s"),
+ vm->def->name,
+ err ? err->message : _("unknown error"));
+ }
+
+ if (vm)
+ virDomainObjUnlock(vm);
+}
+
/*
* Cleanup function for domain that has reached shutoff state.
*
@@ -703,9 +726,10 @@ libxlStartup(int privileged) {
0, NULL, NULL) < 0)
goto error;
- libxlDriverUnlock(libxl_driver);
+ virHashForEach(libxl_driver->domains.objs, libxlAutostartDomain,
+ libxl_driver);
- /* TODO: autostart domains */
+ libxlDriverUnlock(libxl_driver);
return 0;
@@ -731,9 +755,11 @@ libxlReload(void)
libxl_driver->configDir,
libxl_driver->autostartDir,
0, NULL, libxl_driver);
- libxlDriverUnlock(libxl_driver);
- /* TODO: autostart domains */
+ virHashForEach(libxl_driver->domains.objs, libxlAutostartDomain,
+ libxl_driver);
+
+ libxlDriverUnlock(libxl_driver);
return 0;
}
@@ -2102,6 +2128,105 @@ libxlDomainEventDeregister(virConnectPtr conn,
return ret;
}
+static int
+libxlDomainGetAutostart(virDomainPtr dom, int *autostart)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr vm;
+ int ret = -1;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ libxlDriverUnlock(driver);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ libxlError(VIR_ERR_NO_DOMAIN,
+ _("No domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ *autostart = vm->autostart;
+ ret = 0;
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ return ret;
+}
+
+static int
+libxlDomainSetAutostart(virDomainPtr dom, int autostart)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr vm;
+ char *configFile = NULL, *autostartLink = NULL;
+ int ret = -1;
+
+ libxlDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(dom->uuid, uuidstr);
+ libxlError(VIR_ERR_NO_DOMAIN,
+ _("No domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ if (!vm->persistent) {
+ libxlError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("cannot set autostart for transient domain"));
+ goto cleanup;
+ }
+
+ autostart = (autostart != 0);
+
+ if (vm->autostart != autostart) {
+ if (!(configFile = virDomainConfigFile(driver->configDir, vm->def->name)))
+ goto cleanup;
+ if (!(autostartLink = virDomainConfigFile(driver->autostartDir, vm->def->name)))
+ goto cleanup;
+
+ if (autostart) {
+ int err;
+
+ if ((err = virFileMakePath(driver->autostartDir))) {
+ virReportSystemError(err,
+ _("cannot create autostart directory %s"),
+ driver->autostartDir);
+ goto cleanup;
+ }
+
+ if (symlink(configFile, autostartLink) < 0) {
+ virReportSystemError(errno,
+ _("Failed to create symlink '%s to '%s'"),
+ autostartLink, configFile);
+ goto cleanup;
+ }
+ } else {
+ if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
+ virReportSystemError(errno,
+ _("Failed to delete symlink '%s'"),
+ autostartLink);
+ goto cleanup;
+ }
+ }
+
+ vm->autostart = autostart;
+ }
+ ret = 0;
+
+cleanup:
+ VIR_FREE(configFile);
+ VIR_FREE(autostartLink);
+ if (vm)
+ virDomainObjUnlock(vm);
+ libxlDriverUnlock(driver);
+ return ret;
+}
+
static char *
libxlDomainGetSchedulerType(virDomainPtr dom, int *nparams)
{
@@ -2304,8 +2429,8 @@ static virDriver libxlDriver = {
NULL, /* domainDetachDevice */
NULL, /* domainDetachDeviceFlags */
NULL, /* domainUpdateDeviceFlags */
- NULL, /* domainGetAutostart */
- NULL, /* domainSetAutostart */
+ libxlDomainGetAutostart, /* domainGetAutostart */
+ libxlDomainSetAutostart, /* domainSetAutostart */
libxlDomainGetSchedulerType,/* domainGetSchedulerType */
NULL, /* domainGetSchedulerParameters */
NULL, /* domainSetSchedulerParameters */
--
1.7.4.1
13 years, 8 months
[libvirt] [PATCH 0/6] Add virNodeGetCpuTime() API
by Minoru Usui
Hi, everyone.
I wrote new API called virNodeGetCpuTime().
It returns cumulative cpu time of the node from /proc/stat since node boots up.
Previous discussion is here.
http://www.mail-archive.com/libvir-list@redhat.com/msg32552.html
Minoru Usui (6):
[1/6] virNodeGetCpuTime: Expose new API
[2/6] virNodeGetCpuTime: Define internal driver API
[3/6] virNodeGetCpuTime: Implement public API
[4/6] virNodeGetCpuTime: Implement remote protocol
[5/6] virNodeGetCpuTime: Implement virsh support
[6/6] virNodeGetCpuTime: Implement linux support
daemon/remote.c | 23 ++++++++++++
daemon/remote_dispatch_prototypes.h | 8 ++++
daemon/remote_dispatch_ret.h | 1 +
daemon/remote_dispatch_table.h | 5 +++
include/libvirt/libvirt.h.in | 26 ++++++++++++++
src/driver.h | 4 ++
src/esx/esx_driver.c | 1 +
src/libvirt.c | 38 ++++++++++++++++++++
src/libvirt_private.syms | 1 +
src/libvirt_public.syms | 1 +
src/libxl/libxl_driver.c | 1 +
src/lxc/lxc_driver.c | 1 +
src/nodeinfo.c | 60 +++++++++++++++++++++++++++++++
src/nodeinfo.h | 2 +-
src/openvz/openvz_driver.c | 1 +
src/phyp/phyp_driver.c | 1 +
src/qemu/qemu_driver.c | 1 +
src/remote/remote_driver.c | 27 ++++++++++++++
src/remote/remote_protocol.c | 15 ++++++++
src/remote/remote_protocol.h | 11 ++++++
src/remote/remote_protocol.x | 10 +++++-
src/remote_protocol-structs | 6 +++
src/test/test_driver.c | 1 +
src/uml/uml_driver.c | 1 +
src/vbox/vbox_tmpl.c | 1 +
src/vmware/vmware_driver.c | 1 +
src/xen/xen_driver.c | 1 +
src/xenapi/xenapi_driver.c | 1 +
tools/virsh.c | 66 +++++++++++++++++++++++++++++++++++
tools/virsh.pod | 6 +++
30 files changed, 320 insertions(+), 2 deletions(-)
--
Minoru Usui <usui(a)mxm.nes.nec.co.jp>
13 years, 8 months