[libvirt] [PATCH] setmaxmem: remove the code to invoke virDomainSetMemory in cmdSetmaxmem
by Taku Izumi
When the new maximum memory size becomes less than the current memory size,
I think it is not the libvirt client but the each driver that decides the behavior
(reject the operation or shrink the current memory size).
Signed-off-by: Taku Izumi <izumi.taku(a)jp.fujitsu.com>
---
tools/virsh.c | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
Index: libvirt/tools/virsh.c
===================================================================
--- libvirt.orig/tools/virsh.c
+++ libvirt/tools/virsh.c
@@ -3030,15 +3030,7 @@ cmdSetmaxmem(vshControl *ctl, const vshC
if (virDomainSetMaxMemory(dom, kilobytes) != 0) {
vshError(ctl, "%s", _("Unable to change MaxMemorySize"));
- virDomainFree(dom);
- return FALSE;
- }
-
- if (kilobytes < info.memory) {
- if (virDomainSetMemory(dom, kilobytes) != 0) {
- vshError(ctl, "%s", _("Unable to shrink current MemorySize"));
- ret = FALSE;
- }
+ ret = FALSE;
}
virDomainFree(dom);
13 years, 7 months
[libvirt] [BUG] Managed save qemu state gets deleted after failed resume
by Philipp Hahn
Hello,
I haven't had time to provide a fix, but still want you to inform you about a
bug: If resuming a saved VM fails with Qemu-0.14, the managed save state
file /var/lib/libvirt/qemu/save/$VM.save is still deleted. I think it would
be better to only delete the state after an successful resume.
/var/log/libvirt/qemu/ucs2.3-0_basis_amd64.log:
2011-03-30 09:37:56.960: starting up
LC_ALL=C PATH=/sbin:/bin:/usr/sbin:/usr/bin
QEMU_AUDIO_DRV=none /usr/bin/kvm -S
-M pc-0.14 -enable-kvm -m 2048 -smp 2,sockets=2,cores=1,threads=1 -name
ucs2.3-0_basis_amd64 -uuid 656957aa-13a0-6922-5d08-3a39561f9775 -nodefconfig
-nodefaults -chardev
socket,id=monitor,path=/var/lib/libvirt/qemu/ucs2.3-0_basis_amd64.monitor,server,nowait
-mon chardev=monitor,mode=readline -rtc base=utc -boot cnd -drive
file=/var/lib/libvirt/images/ucs_2.3-0-091215-dvd-amd64.iso,if=none,media=cdrom,id=drive-ide0-0-0,readonly=on,format=raw
-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 -drive
file=/var/lib/libvirt/images/ucs230basis.qcow2,if=none,id=drive-ide0-0-1,format=qcow2
-device ide-drive,bus=ide.0,unit=1,drive=drive-ide0-0-1,id=ide0-0-1 -netdev
tap,fd=24,id=hostnet0 -device
rtl8139,netdev=hostnet0,id=net0,mac=52:54:00:12:7c:03,bus=pci.0,addr=0x3 -usb
-device usb-tablet,id=input0 -vnc 0.0.0.0:5 -k de -vga cirrus -device
virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 -option-rom
/usr/share/kvm/pxe-rtl8139.bin
Failed to allocate 2147483648 B: Cannot allocate memory
/var/log/univention/virtual-machine-manager-daemon-errors.log:
libvir: QEMU error : operation failed: migration to 'exec:cat | { dd bs=4096
seek=1 if=/dev/null && dd bs=1048576; }
1<>'/var/lib/libvirt/qemu/save/ucs2.3-0_basis_amd64.save'' failed: migration
failed
libvir: QEMU error : operation failed: failed to retrieve chardev info in qemu
with 'info chardev'
This issue is tracked in our (German) bug-tracker at
<https://forge.univention.org/bugzilla/show_bug.cgi?id=22021>
Sincerely
Philipp Hahn
--
Philipp Hahn Open Source Software Engineer hahn(a)univention.de
Univention GmbH Linux for Your Business fon: +49 421 22 232- 0
Mary-Somerville-Str.1 D-28359 Bremen fax: +49 421 22 232-99
http://www.univention.de/
13 years, 7 months
[libvirt] [PATCH 0/3] reattach pci devices when qemuPrepareHostdevPCIDevices() failed
by Wen Congyang
When I try to attach a pci device to guest OS, libvirtd resets the pci failed.
But I can not use this pci device after attaching pci device failed. I must
rollback the operation by hand.
I think libvirtd should auto rollback the operation when it failed.
Wen Congyang (3):
remove devices from driver->activePciHostdevs when
qemuPrepareHostdevPCIDevices() failed
reattach pci device when pciBindDeviceToStub() failed
reattach pci devices when qemuPrepareHostdevPCIDevices() failed
src/qemu/qemu_hostdev.c | 33 ++++++++++++++---
src/util/pci.c | 90 +++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 107 insertions(+), 16 deletions(-)
13 years, 7 months
[libvirt] [libvirt-snmp][PATCH v4 0/4] Add SNMP trap/notification support
by Michal Privoznik
The fourth version.
In case we build against libvirt older than 0.9.0 (which have old event API),
we need to include some sources from libvirt git. So we are able to run even
on older RHELs, like 5.6. Those files were copied to our git and modified
very slighty.
Finally, we have a proof-of-concept implementation of SNMP trap.
Two new files were first generated using mib2c then edited, so be
careful when re-generating them.
Destination of traps is defined in snmpd.conf (trap2sink), and to
receive them snmptrapd must be configured and up.
The idea behind is - create a thread in which we poll for domain
events. Once we receive event notification, we just fire up
trap sending.
Michal Privoznik (4):
Add notification-type object to libvirt MIB
Add libvirt error handling function
Create functions to fill in and send notification packets.
Add SNMP trap/notification support.
INSTALL.1st | 9 +-
configure.ac | 17 +-
libvirt-snmp.spec.in | 7 +-
src/LIBVIRT-MIB.txt | 9 +
src/Makefile.am | 27 ++-
src/README.txt | 9 +-
src/event.c | 193 ++++++++++++
src/event.h | 101 ++++++
src/event_poll.c | 724 ++++++++++++++++++++++++++++++++++++++++++++
src/event_poll.h | 132 ++++++++
src/ignore-value.h | 64 ++++
src/internal.h | 265 ++++++++++++++++
src/libvirtNotifications.c | 122 ++++++++
src/libvirtNotifications.h | 33 ++
src/libvirtSnmp.c | 136 ++++++++-
src/libvirtSnmpError.c | 34 ++
src/libvirtSnmpError.h | 31 ++
src/memory.c | 313 +++++++++++++++++++
src/memory.h | 212 +++++++++++++
src/threads.c | 251 +++++++++++++++
src/threads.h | 101 ++++++
src/util.c | 105 +++++++
src/util.h | 38 +++
23 files changed, 2919 insertions(+), 14 deletions(-)
create mode 100644 src/event.c
create mode 100644 src/event.h
create mode 100644 src/event_poll.c
create mode 100644 src/event_poll.h
create mode 100644 src/ignore-value.h
create mode 100644 src/internal.h
create mode 100644 src/libvirtNotifications.c
create mode 100644 src/libvirtNotifications.h
create mode 100644 src/libvirtSnmpError.c
create mode 100644 src/libvirtSnmpError.h
create mode 100644 src/memory.c
create mode 100644 src/memory.h
create mode 100644 src/threads.c
create mode 100644 src/threads.h
create mode 100644 src/util.c
create mode 100644 src/util.h
--
1.7.4
13 years, 7 months
[libvirt] [PATCH] qemu: unlock qemu driver before return
by Hu Tao
---
src/qemu/qemu_driver.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 104e92d..6e3edde 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2068,12 +2068,14 @@ static int qemudDomainSave(virDomainPtr dom, const char *path)
qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("Invalid save image format specified "
"in configuration file"));
+ qemuDriverUnlock(driver);
return -1;
}
if (!qemudCompressProgramAvailable(compressed)) {
qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("Compression program for image format "
"in configuration file isn't available"));
+ qemuDriverUnlock(driver);
return -1;
}
}
--
1.7.3.1
13 years, 7 months
[libvirt] [PATCH 0/2] Log enhancement
by Naoya Horiguchi
Hi,
Following patches improve logging feature of libvirt.
Please see individual patches for more details.
[PATCH 1/2] extend logging to record configuration-related events on host machine
[PATCH 2/2] qemu: extend logging to record guest configuration events
Thanks,
Naoya Horiguchi
13 years, 7 months
[libvirt] [PATCH] Allow relative path for qemu backing file
by Jesse Cook
This patch enables the relative backing file path support provided by
qemu-img create.
If a relative path is specified for the backing file, it is converted
to an absolute path using the storage pool path. The absolute path is
used to verify that the backing file exists. If the backing file exists,
the relative path is allowed and will be provided to qemu-img create.
This patch takes the place of a previous patch:
http://www.redhat.com/archives/libvir-list/2011-March/msg00179.html
---
src/storage/storage_backend.c | 18 +++++++++++++++++-
1 files changed, 17 insertions(+), 1 deletions(-)
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index 2eede74..abdc2dd 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -666,6 +666,9 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
}
if (vol->backingStore.path) {
+ int accessRetCode = -1;
+
+ char *absolutePath = NULL;
/* XXX: Not strictly required: qemu-img has an option a different
* backing store, not really sure what use it serves though, and it
@@ -686,7 +689,20 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
vol->backingStore.format);
return -1;
}
- if (access(vol->backingStore.path, R_OK) != 0) {
+
+ /* Convert relative backing store paths to absolute paths for access
+ * validation.
+ */
+ if ('/' != *(vol->backingStore.path)) {
+ virAsprintf(&absolutePath, "%s/%s", pool->def->target.path,
+ vol->backingStore.path);
+
+ } else {
+ virAsprintf(&absolutePath, "%s", vol->backingStore.path);
+ }
+ accessRetCode = access(absolutePath, R_OK);
+ VIR_FREE(absolutePath);
+ if (accessRetCode != 0) {
virReportSystemError(errno,
_("inaccessible backing store volume %s"),
vol->backingStore.path);
--
1.7.4.1
13 years, 7 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, 7 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, 7 months