[libvirt] [PATCH 0/3] Allow on-the-fly migration speed changes

Currently the migration bandwidth cap must be set at the time migration is initiated. This series allows it to be optionally change on the fly too, allowing mgmt apps to adapt to changing conditions

It is possible to set a migration speed limit when starting migration. This new API allows the speed limit to be changed on the fly to adjust to changing conditions * src/driver.h, src/libvirt.c, src/libvirt_public.syms, include/libvirt/libvirt.h.in: Add virDomainMigrateSetMaxSpeed * src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/opennebula/one_driver.c, src/openvz/openvz_driver.c, src/phyp/phyp_driver.c, src/qemu/qemu_driver.c, src/remote/remote_driver.c, src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c, src/vmware/vmware_driver.c, src/xen/xen_driver.c: Stub new API --- include/libvirt/libvirt.h.in | 4 +++ src/driver.h | 5 ++++ src/esx/esx_driver.c | 1 + src/libvirt.c | 47 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 1 + src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/opennebula/one_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 1 + 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 + 17 files changed, 70 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index fcca39d..1cf9273 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -436,6 +436,10 @@ int virDomainMigrateSetMaxDowntime (virDomainPtr domain, unsigned long long downtime, unsigned int flags); +int virDomainMigrateSetMaxSpeed(virDomainPtr domain, + unsigned long bandwidth, + unsigned int flags); + /** * VIR_NODEINFO_MAXCPUS: * @nodeinfo: virNodeInfo instance diff --git a/src/driver.h b/src/driver.h index f03d290..286130a 100644 --- a/src/driver.h +++ b/src/driver.h @@ -442,6 +442,10 @@ typedef int (*virDrvDomainMigrateSetMaxDowntime)(virDomainPtr domain, unsigned long long downtime, unsigned int flags); +typedef int + (*virDrvDomainMigrateSetMaxSpeed)(virDomainPtr domain, + unsigned long bandwidth, + unsigned int flags); typedef int (*virDrvDomainEventRegisterAny)(virConnectPtr conn, @@ -618,6 +622,7 @@ struct _virDriver { virDrvDomainGetJobInfo domainGetJobInfo; virDrvDomainAbortJob domainAbortJob; virDrvDomainMigrateSetMaxDowntime domainMigrateSetMaxDowntime; + virDrvDomainMigrateSetMaxSpeed domainMigrateSetMaxSpeed; virDrvDomainEventRegisterAny domainEventRegisterAny; virDrvDomainEventDeregisterAny domainEventDeregisterAny; virDrvDomainManagedSave domainManagedSave; diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 4f013e8..deda372 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4658,6 +4658,7 @@ static virDriver esxDriver = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ + NULL, /* domainMigrateSetMaxSpeed */ NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ NULL, /* domainManagedSave */ diff --git a/src/libvirt.c b/src/libvirt.c index e7c4cc5..e46c18b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -12557,6 +12557,53 @@ error: } /** + * virDomainMigrateSetMaxSpeed: + * @domain: a domain object + * @bandwidth: migration bandwidth limit in Mbps + * @flags: fine-tuning flags, currently unused, use 0 + * + * The maximum bandwidth (in Mbps) that will be used to do migration + * can be specified with the bandwidth parameter. Not all hypervisors + * will support a bandwidth cap + * + * Returns 0 in case of success, -1 otherwise. + */ +int +virDomainMigrateSetMaxSpeed(virDomainPtr domain, + unsigned long bandwidth, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "bandwidth=%lu, flags=%u", bandwidth, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + conn = domain->conn; + if (conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainMigrateSetMaxSpeed) { + if (conn->driver->domainMigrateSetMaxSpeed(domain, bandwidth, flags) < 0) + goto error; + return 0; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); +error: + virDispatchError(conn); + return -1; +} + +/** * virConnectDomainEventRegisterAny: * @conn: pointer to the connection * @dom: pointer to the domain diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index c027bf7..af25197 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -431,6 +431,7 @@ LIBVIRT_0.9.0 { virDomainSetMemoryFlags; virEventRegisterDefaultImpl; virEventRunDefaultImpl; + virDomainMigrateSetMaxSpeed; } LIBVIRT_0.8.8; # .... define new API here using predicted next version number .... diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 615cb47..254c75f 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -1414,6 +1414,7 @@ static virDriver libxlDriver = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ + NULL, /* domainMigrateSetMaxSpeed */ NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ NULL, /* domainManagedSave */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 0796471..ac6c430 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2891,6 +2891,7 @@ static virDriver lxcDriver = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ + NULL, /* domainMigrateSetMaxSpeed */ lxcDomainEventRegisterAny, /* domainEventRegisterAny */ lxcDomainEventDeregisterAny, /* domainEventDeregisterAny */ NULL, /* domainManagedSave */ diff --git a/src/opennebula/one_driver.c b/src/opennebula/one_driver.c index f3c71ad..3146589 100644 --- a/src/opennebula/one_driver.c +++ b/src/opennebula/one_driver.c @@ -815,6 +815,7 @@ static virDriver oneDriver = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ + NULL, /* domainMigrateSetMaxSpeed */ NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ NULL, /* domainManagedSave */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 7792136..fb30c37 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1637,6 +1637,7 @@ static virDriver openvzDriver = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ + NULL, /* domainMigrateSetMaxSpeed */ NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ NULL, /* domainManagedSave */ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index b06b3b3..51f9ff6 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -4038,6 +4038,7 @@ static virDriver phypDriver = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ + NULL, /* domainMigrateSetMaxSpeed */ NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ NULL, /* domainManagedSave */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 10fe595..93cae00 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7122,6 +7122,7 @@ static virDriver qemuDriver = { qemuDomainGetJobInfo, /* domainGetJobInfo */ qemuDomainAbortJob, /* domainAbortJob */ qemuDomainMigrateSetMaxDowntime, /* domainMigrateSetMaxDowntime */ + NULL, /* domainMigrateSetMaxSpeed */ qemuDomainEventRegisterAny, /* domainEventRegisterAny */ qemuDomainEventDeregisterAny, /* domainEventDeregisterAny */ qemuDomainManagedSave, /* domainManagedSave */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 519c9fa..8741a87 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -11210,6 +11210,7 @@ static virDriver remote_driver = { remoteDomainGetJobInfo, /* domainGetJobInfo */ remoteDomainAbortJob, /* domainFinishJob */ remoteDomainMigrateSetMaxDowntime, /* domainMigrateSetMaxDowntime */ + NULL, /* domainMigrateSetMaxSpeed */ remoteDomainEventRegisterAny, /* domainEventRegisterAny */ remoteDomainEventDeregisterAny, /* domainEventDeregisterAny */ remoteDomainManagedSave, /* domainManagedSave */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 5f2aed6..17f5ad9 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5430,6 +5430,7 @@ static virDriver testDriver = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ + NULL, /* domainMigrateSetMaxSpeed */ testDomainEventRegisterAny, /* domainEventRegisterAny */ testDomainEventDeregisterAny, /* domainEventDeregisterAny */ NULL, /* domainManagedSave */ diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 7f28ede..9f09289 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2232,6 +2232,7 @@ static virDriver umlDriver = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ + NULL, /* domainMigrateSetMaxSpeed */ NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ NULL, /* domainManagedSave */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index e8ac48f..8bd27dd 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8625,6 +8625,7 @@ virDriver NAME(Driver) = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ + NULL, /* domainMigrateSetMaxSpeed */ #if VBOX_API_VERSION == 2002 || VBOX_API_VERSION == 4000 NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index b9f523f..b5e416b 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -990,6 +990,7 @@ static virDriver vmwareDriver = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ + NULL, /* domainMigrateSetMaxSpeed */ NULL, /* domainEventRegisterAny */ NULL, /* domainEventDeregisterAny */ NULL, /* domainManagedSave */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index db147a4..2d0fbf5 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2124,6 +2124,7 @@ static virDriver xenUnifiedDriver = { NULL, /* domainGetJobInfo */ NULL, /* domainAbortJob */ NULL, /* domainMigrateSetMaxDowntime */ + NULL, /* domainMigrateSetMaxSpeed */ xenUnifiedDomainEventRegisterAny, /* domainEventRegisterAny */ xenUnifiedDomainEventDeregisterAny, /* domainEventDeregisterAny */ NULL, /* domainManagedSave */ -- 1.7.4

On 03/21/2011 10:13 AM, Daniel P. Berrange wrote:
It is possible to set a migration speed limit when starting migration. This new API allows the speed limit to be changed on the fly to adjust to changing conditions
* src/driver.h, src/libvirt.c, src/libvirt_public.syms, include/libvirt/libvirt.h.in: Add virDomainMigrateSetMaxSpeed * src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/opennebula/one_driver.c, src/openvz/openvz_driver.c, src/phyp/phyp_driver.c, src/qemu/qemu_driver.c, src/remote/remote_driver.c, src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c, src/vmware/vmware_driver.c, src/xen/xen_driver.c: Stub new API
Missing mention of the new libxl driver...
--- include/libvirt/libvirt.h.in | 4 +++ src/driver.h | 5 ++++ src/esx/esx_driver.c | 1 + src/libvirt.c | 47 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 1 + src/libxl/libxl_driver.c | 1 +
but the diffstat shows you picked it up :)
+++ b/include/libvirt/libvirt.h.in @@ -436,6 +436,10 @@ int virDomainMigrateSetMaxDowntime (virDomainPtr domain, unsigned long long downtime, unsigned int flags);
+int virDomainMigrateSetMaxSpeed(virDomainPtr domain, + unsigned long bandwidth, + unsigned int flags);
Hmm - SetMaxDowntime and SetMaxSpeed; this looks like we might be running into scalability issues. Are there likely to ever be other migration parameters worth setting on the fly? If so, is it better to come up with an all-inclusive API, more like the memory and blkio parameters have recently done (where you pass in a string-name/union-value mapping for each parameter of interest through a single API)? However, if we think that there won't be too many other migration parameters to be tweaked, then this looks fine.
/** + * virDomainMigrateSetMaxSpeed: + * @domain: a domain object + * @bandwidth: migration bandwidth limit in Mbps + * @flags: fine-tuning flags, currently unused, use 0 + * + * The maximum bandwidth (in Mbps) that will be used to do migration + * can be specified with the bandwidth parameter. Not all hypervisors + * will support a bandwidth cap + * + * Returns 0 in case of success, -1 otherwise. + */
Looks reasonable.
+++ b/src/libvirt_public.syms @@ -431,6 +431,7 @@ LIBVIRT_0.9.0 { virDomainSetMemoryFlags; virEventRegisterDefaultImpl; virEventRunDefaultImpl; + virDomainMigrateSetMaxSpeed;
Should this list stay sorted? ACK with those nits addressed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Mon, Mar 21, 2011 at 11:55:58AM -0600, Eric Blake wrote:
On 03/21/2011 10:13 AM, Daniel P. Berrange wrote:
It is possible to set a migration speed limit when starting migration. This new API allows the speed limit to be changed on the fly to adjust to changing conditions
* src/driver.h, src/libvirt.c, src/libvirt_public.syms, include/libvirt/libvirt.h.in: Add virDomainMigrateSetMaxSpeed * src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/opennebula/one_driver.c, src/openvz/openvz_driver.c, src/phyp/phyp_driver.c, src/qemu/qemu_driver.c, src/remote/remote_driver.c, src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c, src/vmware/vmware_driver.c, src/xen/xen_driver.c: Stub new API
Missing mention of the new libxl driver...
--- include/libvirt/libvirt.h.in | 4 +++ src/driver.h | 5 ++++ src/esx/esx_driver.c | 1 + src/libvirt.c | 47 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 1 + src/libxl/libxl_driver.c | 1 +
but the diffstat shows you picked it up :)
+++ b/include/libvirt/libvirt.h.in @@ -436,6 +436,10 @@ int virDomainMigrateSetMaxDowntime (virDomainPtr domain, unsigned long long downtime, unsigned int flags);
+int virDomainMigrateSetMaxSpeed(virDomainPtr domain, + unsigned long bandwidth, + unsigned int flags);
Hmm - SetMaxDowntime and SetMaxSpeed; this looks like we might be running into scalability issues. Are there likely to ever be other migration parameters worth setting on the fly? If so, is it better to come up with an all-inclusive API, more like the memory and blkio parameters have recently done (where you pass in a string-name/union-value mapping for each parameter of interest through a single API)?
I think that would be overkill here.
+++ b/src/libvirt_public.syms @@ -431,6 +431,7 @@ LIBVIRT_0.9.0 { virDomainSetMemoryFlags; virEventRegisterDefaultImpl; virEventRunDefaultImpl; + virDomainMigrateSetMaxSpeed;
Should this list stay sorted?
It could do Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Tue, Mar 22, 2011 at 11:01:31AM +0000, Daniel P. Berrange wrote:
On Mon, Mar 21, 2011 at 11:55:58AM -0600, Eric Blake wrote:
On 03/21/2011 10:13 AM, Daniel P. Berrange wrote:
It is possible to set a migration speed limit when starting migration. This new API allows the speed limit to be changed on the fly to adjust to changing conditions
* src/driver.h, src/libvirt.c, src/libvirt_public.syms, include/libvirt/libvirt.h.in: Add virDomainMigrateSetMaxSpeed * src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/opennebula/one_driver.c, src/openvz/openvz_driver.c, src/phyp/phyp_driver.c, src/qemu/qemu_driver.c, src/remote/remote_driver.c, src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c, src/vmware/vmware_driver.c, src/xen/xen_driver.c: Stub new API
Missing mention of the new libxl driver...
--- include/libvirt/libvirt.h.in | 4 +++ src/driver.h | 5 ++++ src/esx/esx_driver.c | 1 + src/libvirt.c | 47 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 1 + src/libxl/libxl_driver.c | 1 +
but the diffstat shows you picked it up :)
+++ b/include/libvirt/libvirt.h.in @@ -436,6 +436,10 @@ int virDomainMigrateSetMaxDowntime (virDomainPtr domain, unsigned long long downtime, unsigned int flags);
+int virDomainMigrateSetMaxSpeed(virDomainPtr domain, + unsigned long bandwidth, + unsigned int flags);
Hmm - SetMaxDowntime and SetMaxSpeed; this looks like we might be running into scalability issues. Are there likely to ever be other migration parameters worth setting on the fly? If so, is it better to come up with an all-inclusive API, more like the memory and blkio parameters have recently done (where you pass in a string-name/union-value mapping for each parameter of interest through a single API)?
I think that would be overkill here.
Agreed in this case too, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

* src/remote/remote_protocol.x: Define wire protocol * daemon/remote.c, src/remote/remote_driver.c: Add new functions for virDomainMigrateSetSpeed API * src/remote/remote_protocol.c, src/remote/remote_protocol.h, daemon/remote_dispatch_args.h, daemon/remote_dispatch_prototypes.h, daemon/remote_dispatch_table.h: Re-generate files --- daemon/remote.c | 28 ++++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++++++ daemon/remote_dispatch_table.h | 5 +++++ src/remote/remote_driver.c | 31 ++++++++++++++++++++++++++++++- src/remote/remote_protocol.c | 13 +++++++++++++ src/remote/remote_protocol.h | 10 ++++++++++ src/remote/remote_protocol.x | 9 ++++++++- 8 files changed, 103 insertions(+), 2 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index f410982..a8fef4d 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -6563,6 +6563,34 @@ remoteDispatchDomainMigrateSetMaxDowntime(struct qemud_server *server ATTRIBUTE_ } static int +remoteDispatchDomainMigrateSetMaxSpeed(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_migrate_set_max_speed_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virDomainPtr dom; + + dom = get_nonnull_domain(conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + if (virDomainMigrateSetMaxSpeed(dom, args->bandwidth, args->flags) == -1) { + virDomainFree(dom); + remoteDispatchConnError(rerr, conn); + return -1; + } + + virDomainFree(dom); + + return 0; +} + +static int remoteDispatchDomainSnapshotCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h index b32ae1f..15fa1a0 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -175,3 +175,4 @@ remote_domain_set_memory_flags_args val_remote_domain_set_memory_flags_args; remote_domain_set_blkio_parameters_args val_remote_domain_set_blkio_parameters_args; remote_domain_get_blkio_parameters_args val_remote_domain_get_blkio_parameters_args; + remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args; diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h index 4db6c76..3fcf87c 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -482,6 +482,14 @@ static int remoteDispatchDomainMigrateSetMaxDowntime( remote_error *err, remote_domain_migrate_set_max_downtime_args *args, void *ret); +static int remoteDispatchDomainMigrateSetMaxSpeed( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_message_header *hdr, + remote_error *err, + remote_domain_migrate_set_max_speed_args *args, + void *ret); static int remoteDispatchDomainOpenConsole( struct qemud_server *server, struct qemud_client *client, diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index c50d038..c5f6653 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1037,3 +1037,8 @@ .args_filter = (xdrproc_t) xdr_remote_domain_get_blkio_parameters_args, .ret_filter = (xdrproc_t) xdr_remote_domain_get_blkio_parameters_ret, }, +{ /* DomainMigrateSetMaxSpeed => 207 */ + .fn = (dispatch_fn) remoteDispatchDomainMigrateSetMaxSpeed, + .args_filter = (xdrproc_t) xdr_remote_domain_migrate_set_max_speed_args, + .ret_filter = (xdrproc_t) xdr_void, +}, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 8741a87..19df3ff 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -9214,6 +9214,35 @@ done: return rv; } +static int +remoteDomainMigrateSetMaxSpeed(virDomainPtr domain, + unsigned long bandwidth, + unsigned int flags) +{ + struct private_data *priv = domain->conn->privateData; + remote_domain_migrate_set_max_speed_args args; + int rv = -1; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, domain); + args.bandwidth = bandwidth; + args.flags = flags; + + if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED, + (xdrproc_t) xdr_remote_domain_migrate_set_max_speed_args, + (char *) &args, + (xdrproc_t) xdr_void, + (char *) NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + static virDomainSnapshotPtr remoteDomainSnapshotCreateXML(virDomainPtr domain, const char *xmlDesc, @@ -11210,7 +11239,7 @@ static virDriver remote_driver = { remoteDomainGetJobInfo, /* domainGetJobInfo */ remoteDomainAbortJob, /* domainFinishJob */ remoteDomainMigrateSetMaxDowntime, /* domainMigrateSetMaxDowntime */ - NULL, /* domainMigrateSetMaxSpeed */ + remoteDomainMigrateSetMaxSpeed, /* domainMigrateSetMaxSpeed */ remoteDomainEventRegisterAny, /* domainEventRegisterAny */ remoteDomainEventDeregisterAny, /* domainEventDeregisterAny */ remoteDomainManagedSave, /* domainManagedSave */ diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index ea2bdf7..7ecea9d 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -3508,6 +3508,19 @@ xdr_remote_domain_migrate_set_max_downtime_args (XDR *xdrs, remote_domain_migrat } bool_t +xdr_remote_domain_migrate_set_max_speed_args (XDR *xdrs, remote_domain_migrate_set_max_speed_args *objp) +{ + + if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) + return FALSE; + if (!xdr_uint64_t (xdrs, &objp->bandwidth)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_domain_events_register_any_args (XDR *xdrs, remote_domain_events_register_any_args *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index a55f7c4..87de0da 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -1982,6 +1982,13 @@ struct remote_domain_migrate_set_max_downtime_args { }; typedef struct remote_domain_migrate_set_max_downtime_args remote_domain_migrate_set_max_downtime_args; +struct remote_domain_migrate_set_max_speed_args { + remote_nonnull_domain dom; + uint64_t bandwidth; + u_int flags; +}; +typedef struct remote_domain_migrate_set_max_speed_args remote_domain_migrate_set_max_speed_args; + struct remote_domain_events_register_any_args { int eventID; }; @@ -2387,6 +2394,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_SET_MEMORY_FLAGS = 204, REMOTE_PROC_DOMAIN_SET_BLKIO_PARAMETERS = 205, REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, + REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, }; typedef enum remote_procedure remote_procedure; @@ -2736,6 +2744,7 @@ extern bool_t xdr_remote_domain_get_job_info_args (XDR *, remote_domain_get_job extern bool_t xdr_remote_domain_get_job_info_ret (XDR *, remote_domain_get_job_info_ret*); extern bool_t xdr_remote_domain_abort_job_args (XDR *, remote_domain_abort_job_args*); extern bool_t xdr_remote_domain_migrate_set_max_downtime_args (XDR *, remote_domain_migrate_set_max_downtime_args*); +extern bool_t xdr_remote_domain_migrate_set_max_speed_args (XDR *, remote_domain_migrate_set_max_speed_args*); extern bool_t xdr_remote_domain_events_register_any_args (XDR *, remote_domain_events_register_any_args*); extern bool_t xdr_remote_domain_events_deregister_any_args (XDR *, remote_domain_events_deregister_any_args*); extern bool_t xdr_remote_domain_event_reboot_msg (XDR *, remote_domain_event_reboot_msg*); @@ -3090,6 +3099,7 @@ extern bool_t xdr_remote_domain_get_job_info_args (); extern bool_t xdr_remote_domain_get_job_info_ret (); extern bool_t xdr_remote_domain_abort_job_args (); extern bool_t xdr_remote_domain_migrate_set_max_downtime_args (); +extern bool_t xdr_remote_domain_migrate_set_max_speed_args (); extern bool_t xdr_remote_domain_events_register_any_args (); extern bool_t xdr_remote_domain_events_deregister_any_args (); extern bool_t xdr_remote_domain_event_reboot_msg (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index aa710a4..7310689 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -1760,6 +1760,12 @@ struct remote_domain_migrate_set_max_downtime_args { unsigned flags; }; +struct remote_domain_migrate_set_max_speed_args { + remote_nonnull_domain dom; + unsigned hyper bandwidth; + unsigned flags; +}; + struct remote_domain_events_register_any_args { int eventID; }; @@ -2152,7 +2158,8 @@ enum remote_procedure { REMOTE_PROC_GET_SYSINFO = 203, REMOTE_PROC_DOMAIN_SET_MEMORY_FLAGS = 204, REMOTE_PROC_DOMAIN_SET_BLKIO_PARAMETERS = 205, - REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206 + REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, + REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207 /* * Notice how the entries are grouped in sets of 10 ? -- 1.7.4

On 03/21/2011 10:13 AM, Daniel P. Berrange wrote:
* src/remote/remote_protocol.x: Define wire protocol * daemon/remote.c, src/remote/remote_driver.c: Add new functions for virDomainMigrateSetSpeed API * src/remote/remote_protocol.c, src/remote/remote_protocol.h, daemon/remote_dispatch_args.h, daemon/remote_dispatch_prototypes.h, daemon/remote_dispatch_table.h: Re-generate files --- daemon/remote.c | 28 ++++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++++++ daemon/remote_dispatch_table.h | 5 +++++ src/remote/remote_driver.c | 31 ++++++++++++++++++++++++++++++- src/remote/remote_protocol.c | 13 +++++++++++++ src/remote/remote_protocol.h | 10 ++++++++++ src/remote/remote_protocol.x | 9 ++++++++- 8 files changed, 103 insertions(+), 2 deletions(-)
No change to src/remote_protocol-structs (make check should have caught that, if you have 'dwarves' installed)? Also, that file has a pending unreviewed patch from me that might conflict, depending on who pushes first: https://www.redhat.com/archives/libvir-list/2011-March/msg00519.html
+++ b/src/remote/remote_protocol.x @@ -1760,6 +1760,12 @@ struct remote_domain_migrate_set_max_downtime_args { unsigned flags; };
+struct remote_domain_migrate_set_max_speed_args { + remote_nonnull_domain dom; + unsigned hyper bandwidth; + unsigned flags; +};
Do we really need 'unsigned long' in patch 1 and 'hyper' here? Given that the argument is provided in units of Mbps, wouldn't 'int' be sufficient? However, this accurately reflects patch 1, so a change here would also require a change in patch 1. ACK with the nits addressed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Mon, Mar 21, 2011 at 12:04:33PM -0600, Eric Blake wrote:
On 03/21/2011 10:13 AM, Daniel P. Berrange wrote:
* src/remote/remote_protocol.x: Define wire protocol * daemon/remote.c, src/remote/remote_driver.c: Add new functions for virDomainMigrateSetSpeed API * src/remote/remote_protocol.c, src/remote/remote_protocol.h, daemon/remote_dispatch_args.h, daemon/remote_dispatch_prototypes.h, daemon/remote_dispatch_table.h: Re-generate files --- daemon/remote.c | 28 ++++++++++++++++++++++++++++ daemon/remote_dispatch_args.h | 1 + daemon/remote_dispatch_prototypes.h | 8 ++++++++ daemon/remote_dispatch_table.h | 5 +++++ src/remote/remote_driver.c | 31 ++++++++++++++++++++++++++++++- src/remote/remote_protocol.c | 13 +++++++++++++ src/remote/remote_protocol.h | 10 ++++++++++ src/remote/remote_protocol.x | 9 ++++++++- 8 files changed, 103 insertions(+), 2 deletions(-)
No change to src/remote_protocol-structs (make check should have caught that, if you have 'dwarves' installed)? Also, that file has a pending unreviewed patch from me that might conflict, depending on who pushes first: https://www.redhat.com/archives/libvir-list/2011-March/msg00519.html
Ipps, i forgot that.
+++ b/src/remote/remote_protocol.x @@ -1760,6 +1760,12 @@ struct remote_domain_migrate_set_max_downtime_args { unsigned flags; };
+struct remote_domain_migrate_set_max_speed_args { + remote_nonnull_domain dom; + unsigned hyper bandwidth; + unsigned flags; +};
Do we really need 'unsigned long' in patch 1 and 'hyper' here? Given that the argument is provided in units of Mbps, wouldn't 'int' be sufficient? However, this accurately reflects patch 1, so a change here would also require a change in patch 1.
I used 'unsigned long' and 'hyper' for consistency with the way this same value is serialized in the main migrate method: virDomainPtr virDomainMigrate (virDomainPtr domain, virConnectPtr dconn, unsigned long flags, const char *dname, const char *uri, unsigned long bandwidth); 'bandwidth' is the parameter mirror here struct remote_domain_migrate_perform_args { remote_nonnull_domain dom; opaque cookie<REMOTE_MIGRATE_COOKIE_MAX>; remote_nonnull_string uri; unsigned hyper flags; remote_string dname; unsigned hyper resource; }; while 'resource' is the one we mirror here Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Enhance the QEMU migration monitoring loop, so that it can get a signal to change migration speed on the fly * src/qemu/qemu_domain.h: Add signal for changing speed on the fly * src/qemu/qemu_driver.c: Wire up virDomainMigrateSetSpeed driver * src/qemu/qemu_migration.c: Support signal for changing speed --- src/qemu/qemu_domain.h | 2 + src/qemu/qemu_driver.c | 51 ++++++++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_migration.c | 11 +++++++++ 3 files changed, 63 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index ebb2050..8258900 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -45,10 +45,12 @@ enum qemuDomainJobSignals { QEMU_JOB_SIGNAL_CANCEL = 1 << 0, /* Request job cancellation */ QEMU_JOB_SIGNAL_SUSPEND = 1 << 1, /* Request VM suspend to finish live migration offline */ QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME = 1 << 2, /* Request migration downtime change */ + QEMU_JOB_SIGNAL_MIGRATE_SPEED = 1 << 3, /* Request migration speed change */ }; struct qemuDomainJobSignalsData { unsigned long long migrateDowntime; /* Data for QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME */ + unsigned long migrateBandwidth; /* Data for QEMU_JOB_SIGNAL_MIGRATE_SPEED */ }; typedef struct _qemuDomainPCIAddressSet qemuDomainPCIAddressSet; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 93cae00..fd2eced 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6071,6 +6071,55 @@ cleanup: return ret; } +static int +qemuDomainMigrateSetMaxSpeed(virDomainPtr dom, + unsigned long bandwidth, + unsigned int flags) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + qemuDomainObjPrivatePtr priv; + int ret = -1; + + virCheckFlags(0, -1); + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + qemuReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto cleanup; + } + + priv = vm->privateData; + + if (priv->jobActive != QEMU_JOB_MIGRATION_OUT) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not being migrated")); + goto cleanup; + } + + VIR_DEBUG("Requesting migration speed change to %luMbs", bandwidth); + priv->jobSignals |= QEMU_JOB_SIGNAL_MIGRATE_SPEED; + priv->jobSignalsData.migrateBandwidth = bandwidth; + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); + return ret; +} + static char *qemuFindQemuImgBinary(void) { char *ret; @@ -7122,7 +7171,7 @@ static virDriver qemuDriver = { qemuDomainGetJobInfo, /* domainGetJobInfo */ qemuDomainAbortJob, /* domainAbortJob */ qemuDomainMigrateSetMaxDowntime, /* domainMigrateSetMaxDowntime */ - NULL, /* domainMigrateSetMaxSpeed */ + qemuDomainMigrateSetMaxSpeed, /* domainMigrateSetMaxSpeed */ qemuDomainEventRegisterAny, /* domainEventRegisterAny */ qemuDomainEventDeregisterAny, /* domainEventDeregisterAny */ qemuDomainManagedSave, /* domainManagedSave */ diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index f450130..826e1bf 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -144,6 +144,17 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) qemuDomainObjExitMonitorWithDriver(driver, vm); if (rc < 0) VIR_WARN0("Unable to set migration downtime"); + } else if (priv->jobSignals & QEMU_JOB_SIGNAL_MIGRATE_SPEED) { + unsigned long bandwidth = priv->jobSignalsData.migrateBandwidth; + + priv->jobSignals ^= QEMU_JOB_SIGNAL_MIGRATE_SPEED; + priv->jobSignalsData.migrateBandwidth = 0; + VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth); + qemuDomainObjEnterMonitorWithDriver(driver, vm); + rc = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth); + qemuDomainObjExitMonitorWithDriver(driver, vm); + if (rc < 0) + VIR_WARN0("Unable to set migration speed"); } /* Repeat check because the job signals might have caused -- 1.7.4

On 03/21/2011 10:13 AM, Daniel P. Berrange wrote:
Enhance the QEMU migration monitoring loop, so that it can get a signal to change migration speed on the fly
* src/qemu/qemu_domain.h: Add signal for changing speed on the fly * src/qemu/qemu_driver.c: Wire up virDomainMigrateSetSpeed driver * src/qemu/qemu_migration.c: Support signal for changing speed --- src/qemu/qemu_domain.h | 2 + src/qemu/qemu_driver.c | 51 ++++++++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_migration.c | 11 +++++++++ 3 files changed, 63 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index ebb2050..8258900 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -45,10 +45,12 @@ enum qemuDomainJobSignals { QEMU_JOB_SIGNAL_CANCEL = 1 << 0, /* Request job cancellation */ QEMU_JOB_SIGNAL_SUSPEND = 1 << 1, /* Request VM suspend to finish live migration offline */ QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME = 1 << 2, /* Request migration downtime change */ + QEMU_JOB_SIGNAL_MIGRATE_SPEED = 1 << 3, /* Request migration speed change */
Makes it easy to review when you've already got a similar feature to copy from :)
+++ b/src/qemu/qemu_driver.c @@ -6071,6 +6071,55 @@ cleanup: return ret; }
+static int +qemuDomainMigrateSetMaxSpeed(virDomainPtr dom, + unsigned long bandwidth,
Same question as in patch 1 and 2 about whether 'int' is better than 'long' for this parameter. ACK. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Mon, Mar 21, 2011 at 12:07:12PM -0600, Eric Blake wrote:
On 03/21/2011 10:13 AM, Daniel P. Berrange wrote:
Enhance the QEMU migration monitoring loop, so that it can get a signal to change migration speed on the fly
* src/qemu/qemu_domain.h: Add signal for changing speed on the fly * src/qemu/qemu_driver.c: Wire up virDomainMigrateSetSpeed driver * src/qemu/qemu_migration.c: Support signal for changing speed --- src/qemu/qemu_domain.h | 2 + src/qemu/qemu_driver.c | 51 ++++++++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_migration.c | 11 +++++++++ 3 files changed, 63 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index ebb2050..8258900 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -45,10 +45,12 @@ enum qemuDomainJobSignals { QEMU_JOB_SIGNAL_CANCEL = 1 << 0, /* Request job cancellation */ QEMU_JOB_SIGNAL_SUSPEND = 1 << 1, /* Request VM suspend to finish live migration offline */ QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME = 1 << 2, /* Request migration downtime change */ + QEMU_JOB_SIGNAL_MIGRATE_SPEED = 1 << 3, /* Request migration speed change */
Makes it easy to review when you've already got a similar feature to copy from :)
+++ b/src/qemu/qemu_driver.c @@ -6071,6 +6071,55 @@ cleanup: return ret; }
+static int +qemuDomainMigrateSetMaxSpeed(virDomainPtr dom, + unsigned long bandwidth,
Same question as in patch 1 and 2 about whether 'int' is better than 'long' for this parameter.
Again, done for consistency with the existing APIs Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (3)
-
Daniel P. Berrange
-
Daniel Veillard
-
Eric Blake