[libvirt] [PATCH 1/4] qemu: Make Set*Mem commands hotplug only

SetMem and SetMaxMem are hotplug only APIs, any persistent config changes are supposed to go via XML definition. The original implementation of these calls were incorrect and had the nasty side effect of making a psuedo persistent change that would be lost after libvirtd restart (I didn't know any better). Fix these APIs to rightly reject non running domains. --- src/qemu/qemu_driver.c | 54 ++++++++++++++++++++++++++++------------------- 1 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a2be1a3..56a450c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3625,14 +3625,21 @@ static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) { goto cleanup; } + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto cleanup; + } + if (newmax < vm->def->memory) { - qemuReportError(VIR_ERR_INVALID_ARG, - "%s", _("cannot set max memory lower than current memory")); - goto cleanup;; + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("cannot set max memory lower than current memory")); + goto cleanup; } - vm->def->maxmem = newmax; - ret = 0; + /* There isn't any way to change this value for a running qemu guest */ + qemuReportError(VIR_ERR_NO_SUPPORT, + "%s", _("cannot set max memory of an active domain")); cleanup: if (vm) @@ -3643,8 +3650,9 @@ cleanup: static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { struct qemud_driver *driver = dom->conn->privateData; + qemuDomainObjPrivatePtr priv; virDomainObjPtr vm; - int ret = -1; + int ret = -1, r; qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -3657,6 +3665,12 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { goto cleanup; } + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto cleanup; + } + if (newmem > vm->def->maxmem) { qemuReportError(VIR_ERR_INVALID_ARG, "%s", _("cannot set memory higher than max memory")); @@ -3666,25 +3680,21 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; - if (virDomainObjIsActive(vm)) { - qemuDomainObjPrivatePtr priv = vm->privateData; - qemuDomainObjEnterMonitor(vm); - int r = qemuMonitorSetBalloon(priv->mon, newmem); - qemuDomainObjExitMonitor(vm); - if (r < 0) - goto endjob; + priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); + r = qemuMonitorSetBalloon(priv->mon, newmem); + qemuDomainObjExitMonitor(vm); + if (r < 0) + goto endjob; - /* Lack of balloon support is a fatal error */ - if (r == 0) { - qemuReportError(VIR_ERR_NO_SUPPORT, - "%s", _("cannot set memory of an active domain")); - goto endjob; - } - } else { - vm->def->memory = newmem; + /* Lack of balloon support is a fatal error */ + if (r == 0) { + qemuReportError(VIR_ERR_NO_SUPPORT, + "%s", _("cannot set memory of an active domain")); + goto endjob; } - ret = 0; + ret = 0; endjob: if (qemuDomainObjEndJob(vm) == 0) vm = NULL; -- 1.6.5.2

On Fri, Feb 12, 2010 at 10:32:14AM -0500, Cole Robinson wrote:
SetMem and SetMaxMem are hotplug only APIs, any persistent config changes are supposed to go via XML definition. The original implementation of these calls were incorrect and had the nasty side effect of making a psuedo persistent change that would be lost after libvirtd restart (I didn't know any better).
Fix these APIs to rightly reject non running domains. --- src/qemu/qemu_driver.c | 54 ++++++++++++++++++++++++++++------------------- 1 files changed, 32 insertions(+), 22 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a2be1a3..56a450c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3625,14 +3625,21 @@ static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) { goto cleanup; }
+ if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto cleanup; + } + if (newmax < vm->def->memory) { - qemuReportError(VIR_ERR_INVALID_ARG, - "%s", _("cannot set max memory lower than current memory")); - goto cleanup;; + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("cannot set max memory lower than current memory")); + goto cleanup; }
- vm->def->maxmem = newmax; - ret = 0; + /* There isn't any way to change this value for a running qemu guest */ + qemuReportError(VIR_ERR_NO_SUPPORT, + "%s", _("cannot set max memory of an active domain"));
cleanup: if (vm) @@ -3643,8 +3650,9 @@ cleanup:
static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { struct qemud_driver *driver = dom->conn->privateData; + qemuDomainObjPrivatePtr priv; virDomainObjPtr vm; - int ret = -1; + int ret = -1, r;
qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -3657,6 +3665,12 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { goto cleanup; }
+ if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto cleanup; + } + if (newmem > vm->def->maxmem) { qemuReportError(VIR_ERR_INVALID_ARG, "%s", _("cannot set memory higher than max memory")); @@ -3666,25 +3680,21 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { if (qemuDomainObjBeginJob(vm) < 0) goto cleanup;
- if (virDomainObjIsActive(vm)) { - qemuDomainObjPrivatePtr priv = vm->privateData; - qemuDomainObjEnterMonitor(vm); - int r = qemuMonitorSetBalloon(priv->mon, newmem); - qemuDomainObjExitMonitor(vm); - if (r < 0) - goto endjob; + priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); + r = qemuMonitorSetBalloon(priv->mon, newmem); + qemuDomainObjExitMonitor(vm); + if (r < 0) + goto endjob;
- /* Lack of balloon support is a fatal error */ - if (r == 0) { - qemuReportError(VIR_ERR_NO_SUPPORT, - "%s", _("cannot set memory of an active domain")); - goto endjob; - } - } else { - vm->def->memory = newmem; + /* Lack of balloon support is a fatal error */ + if (r == 0) { + qemuReportError(VIR_ERR_NO_SUPPORT, + "%s", _("cannot set memory of an active domain")); + goto endjob; } - ret = 0;
+ ret = 0; endjob: if (qemuDomainObjEndJob(vm) == 0) vm = NULL;
ACK Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On 02/15/2010 06:09 AM, Daniel P. Berrange wrote:
On Fri, Feb 12, 2010 at 10:32:14AM -0500, Cole Robinson wrote:
SetMem and SetMaxMem are hotplug only APIs, any persistent config changes are supposed to go via XML definition. The original implementation of these calls were incorrect and had the nasty side effect of making a psuedo persistent change that would be lost after libvirtd restart (I didn't know any better).
Fix these APIs to rightly reject non running domains.
ACK
Daniel
Thanks, pushed now. Will send a docs patch separately. - Cole

2010/2/12 Cole Robinson <crobinso@redhat.com>:
SetMem and SetMaxMem are hotplug only APIs, any persistent config changes are supposed to go via XML definition. The original implementation of these calls were incorrect and had the nasty side effect of making a psuedo persistent change that would be lost after libvirtd restart (I didn't know any better).
Fix these APIs to rightly reject non running domains. ---
Could you document this somewhere that virDomainSetMaxMemory may be called for active domains only, like in the documentation of virDomainSetMaxMemory in libvirt.c? Several details of the libvirt API are only documentation deep down in the mailing list, or the developers heads. Now you've fixed the code to do what is supposed to do, but it's still not documented well. The same goes for the other commit where you made it callable for an active domain only. Matthias

On Mon, Feb 15, 2010 at 12:33:53PM +0100, Matthias Bolte wrote:
2010/2/12 Cole Robinson <crobinso@redhat.com>:
SetMem and SetMaxMem are hotplug only APIs, any persistent config changes are supposed to go via XML definition. The original implementation of these calls were incorrect and had the nasty side effect of making a psuedo persistent change that would be lost after libvirtd restart (I didn't know any better).
Fix these APIs to rightly reject non running domains. ---
Could you document this somewhere that virDomainSetMaxMemory may be called for active domains only, like in the documentation of virDomainSetMaxMemory in libvirt.c?
Several details of the libvirt API are only documentation deep down in the mailing list, or the developers heads.
Now you've fixed the code to do what is supposed to do, but it's still not documented well.
The same goes for the other commit where you made it callable for an active domain only.
FYI, I also have a test case that's intended to validate methods which should only be called on running domains. If anyone wants to submit patches for API calls which are missing in my current list.... http://libvirt.org/git/?p=libvirt-tck.git;a=blob;f=scripts/domain/090-invali... Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

According to Daniel P. Berrange on 2/15/2010 5:00 AM:
FYI, I also have a test case that's intended to validate methods which should only be called on running domains. If anyone wants to submit patches for API calls which are missing in my current list....
http://libvirt.org/git/?p=libvirt-tck.git;a=blob;f=scripts/domain/090-invali...
I didn't see libvirt-tck.git documented anywhere on the libvirt.org site. Seems like it would be useful to mention somewhere, perhaps on the Downloads page. -- Don't work too hard, make some time for fun as well! Eric Blake ebb9@byu.net

On 02/15/2010 06:33 AM, Matthias Bolte wrote:
2010/2/12 Cole Robinson <crobinso@redhat.com>:
SetMem and SetMaxMem are hotplug only APIs, any persistent config changes are supposed to go via XML definition. The original implementation of these calls were incorrect and had the nasty side effect of making a psuedo persistent change that would be lost after libvirtd restart (I didn't know any better).
Fix these APIs to rightly reject non running domains. ---
Could you document this somewhere that virDomainSetMaxMemory may be called for active domains only, like in the documentation of virDomainSetMaxMemory in libvirt.c?
Several details of the libvirt API are only documentation deep down in the mailing list, or the developers heads.
Now you've fixed the code to do what is supposed to do, but it's still not documented well.
The same goes for the other commit where you made it callable for an active domain only.
Good point. I'll write up a docs patch. Thanks, Cole
participants (4)
-
Cole Robinson
-
Daniel P. Berrange
-
Eric Blake
-
Matthias Bolte