[libvirt] [PATCH v2 0/5] Allow time sync on domain resume

Diff to v1: -Fixed issues raised by Peter Michal Privoznik (5): Introduce virDomainResumeFlags API Implement virDomainResumeFlags in all drivers qemu: Split qemuDomainSetTime into two functions qemuDomainResumeFlags: Introduce VIR_DOMAIN_RESUME_SYNC_TIME virsh: Implement virDomainResumeFlags include/libvirt/libvirt-domain.h | 9 +++ src/driver-hypervisor.h | 5 ++ src/esx/esx_driver.c | 14 ++++- src/hyperv/hyperv_driver.c | 14 ++++- src/libvirt-domain.c | 50 ++++++++++++++++ src/libvirt_public.syms | 5 ++ src/libxl/libxl_driver.c | 14 ++++- src/lxc/lxc_driver.c | 15 ++++- src/openvz/openvz_driver.c | 13 ++++- src/parallels/parallels_driver.c | 11 +++- src/phyp/phyp_driver.c | 12 +++- src/qemu/qemu_driver.c | 119 ++++++++++++++++++++++++++++----------- src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 13 ++++- src/remote_protocol-structs | 5 ++ src/test/test_driver.c | 13 ++++- src/vbox/vbox_common.c | 11 +++- src/vmware/vmware_driver.c | 12 +++- src/xen/xen_driver.c | 14 ++++- src/xenapi/xenapi_driver.c | 21 ++++++- tools/virsh-domain.c | 13 ++++- tools/virsh.pod | 11 ++-- 22 files changed, 339 insertions(+), 56 deletions(-) -- 2.0.4

The old DomainResume API lacks flags argument. This is unfortunate, because there may exist some use cases where an additional work could be done on domain resume. However, without flags it's not possible. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- include/libvirt/libvirt-domain.h | 2 ++ src/driver-hypervisor.h | 5 +++++ src/libvirt-domain.c | 44 ++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 13 +++++++++++- src/remote_protocol-structs | 5 +++++ 7 files changed, 74 insertions(+), 1 deletion(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index b28d37d..1795dd3 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -869,6 +869,8 @@ int virDomainFree (virDomainPtr domain); */ int virDomainSuspend (virDomainPtr domain); int virDomainResume (virDomainPtr domain); +int virDomainResumeFlags (virDomainPtr domain, + unsigned int flags); int virDomainPMSuspendForDuration (virDomainPtr domain, unsigned int target, unsigned long long duration, diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index ad66629..e781475 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -116,6 +116,10 @@ typedef int (*virDrvDomainResume)(virDomainPtr domain); typedef int +(*virDrvDomainResumeFlags)(virDomainPtr domain, + unsigned int flags); + +typedef int (*virDrvDomainPMSuspendForDuration)(virDomainPtr, unsigned int target, unsigned long long duration, @@ -1205,6 +1209,7 @@ struct _virHypervisorDriver { virDrvDomainLookupByName domainLookupByName; virDrvDomainSuspend domainSuspend; virDrvDomainResume domainResume; + virDrvDomainResumeFlags domainResumeFlags; virDrvDomainPMSuspendForDuration domainPMSuspendForDuration; virDrvDomainPMWakeup domainPMWakeup; virDrvDomainShutdown domainShutdown; diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 2b0defc..7d21d77 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -693,6 +693,50 @@ virDomainResume(virDomainPtr domain) /** + * virDomainResumeFlags: + * @domain: a domain object + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * Resume a suspended domain, the process is restarted from the state where + * it was frozen by calling virDomainSuspend(). + * This function may require privileged access + * Moreover, resume may not be supported if domain is in some + * special state like VIR_DOMAIN_PMSUSPENDED. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virDomainResumeFlags(virDomainPtr domain, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain); + + virResetLastError(); + + virCheckDomainReturn(domain, -1); + conn = domain->conn; + + virCheckReadOnlyGoto(conn->flags, error); + + if (conn->driver->domainResumeFlags) { + int ret; + ret = conn->driver->domainResumeFlags(domain, flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(domain->conn); + return -1; +} + + +/** * virDomainPMSuspendForDuration: * @dom: a domain object * @target: a value from virNodeSuspendTarget diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 5f95802..143dabe 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -684,4 +684,9 @@ LIBVIRT_1.2.9 { virNodeAllocPages; } LIBVIRT_1.2.8; +LIBVIRT_1.2.11 { + global: + virDomainResumeFlags; +} LIBVIRT_1.2.9; + # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index d111e10..7d96ea3 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -8241,6 +8241,7 @@ static virHypervisorDriver hypervisor_driver = { .connectGetDomainCapabilities = remoteConnectGetDomainCapabilities, /* 1.2.7 */ .connectGetAllDomainStats = remoteConnectGetAllDomainStats, /* 1.2.8 */ .nodeAllocPages = remoteNodeAllocPages, /* 1.2.9 */ + .domainResumeFlags = remoteDomainResumeFlags, /* 1.2.11 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index ebf4530..c68c7c0 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -803,6 +803,11 @@ struct remote_domain_resume_args { remote_nonnull_domain dom; }; +struct remote_domain_resume_flags_args { + remote_nonnull_domain dom; + unsigned int flags; +}; + struct remote_domain_pm_suspend_for_duration_args { remote_nonnull_domain dom; unsigned int target; @@ -5506,5 +5511,11 @@ enum remote_procedure { * @generate: none * @acl: connect:write */ - REMOTE_PROC_NODE_ALLOC_PAGES = 347 + REMOTE_PROC_NODE_ALLOC_PAGES = 347, + + /** + * @generate: both + * @acl: domain:suspend + */ + REMOTE_PROC_DOMAIN_RESUME_FLAGS = 348 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 362baf9..ce9e35d 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -464,6 +464,10 @@ struct remote_domain_suspend_args { struct remote_domain_resume_args { remote_nonnull_domain dom; }; +struct remote_domain_resume_flags_args { + remote_nonnull_domain dom; + u_int flags; +}; struct remote_domain_pm_suspend_for_duration_args { remote_nonnull_domain dom; u_int target; @@ -2927,4 +2931,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_BLOCK_COPY = 345, REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TUNABLE = 346, REMOTE_PROC_NODE_ALLOC_PAGES = 347, + REMOTE_PROC_DOMAIN_RESUME_FLAGS = 348, }; -- 2.0.4

On 11/06/14 14:01, Michal Privoznik wrote:
The old DomainResume API lacks flags argument. This is unfortunate, because there may exist some use cases where an additional work could be done on domain resume. However, without flags it's not possible.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- include/libvirt/libvirt-domain.h | 2 ++ src/driver-hypervisor.h | 5 +++++ src/libvirt-domain.c | 44 ++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 13 +++++++++++- src/remote_protocol-structs | 5 +++++ 7 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index ebf4530..c68c7c0 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x
@@ -5506,5 +5511,11 @@ enum remote_procedure { * @generate: none * @acl: connect:write */ - REMOTE_PROC_NODE_ALLOC_PAGES = 347 + REMOTE_PROC_NODE_ALLOC_PAGES = 347, + + /** + * @generate: both + * @acl: domain:suspend + */ + REMOTE_PROC_DOMAIN_RESUME_FLAGS = 348
You will have merge conflicts here.
}; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 362baf9..ce9e35d 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -464,6 +464,10 @@ struct remote_domain_suspend_args { struct remote_domain_resume_args { remote_nonnull_domain dom; }; +struct remote_domain_resume_flags_args { + remote_nonnull_domain dom; + u_int flags; +}; struct remote_domain_pm_suspend_for_duration_args { remote_nonnull_domain dom; u_int target; @@ -2927,4 +2931,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_BLOCK_COPY = 345, REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TUNABLE = 346, REMOTE_PROC_NODE_ALLOC_PAGES = 347, + REMOTE_PROC_DOMAIN_RESUME_FLAGS = 348, };
ACK, Peter

This practically boils down to: 1) rename DomainResume implementation to DomainResumeFlags 2) make DomainResume call DomainResumeFlags(dom, 0); Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/esx/esx_driver.c | 14 +++++++++++++- src/hyperv/hyperv_driver.c | 14 +++++++++++++- src/libxl/libxl_driver.c | 14 ++++++++++++-- src/lxc/lxc_driver.c | 15 +++++++++++++-- src/openvz/openvz_driver.c | 13 ++++++++++++- src/parallels/parallels_driver.c | 11 ++++++++++- src/phyp/phyp_driver.c | 12 +++++++++++- src/qemu/qemu_driver.c | 15 +++++++++++++-- src/test/test_driver.c | 13 ++++++++++++- src/vbox/vbox_common.c | 11 ++++++++++- src/vmware/vmware_driver.c | 12 +++++++++++- src/xen/xen_driver.c | 14 ++++++++++++-- src/xenapi/xenapi_driver.c | 21 +++++++++++++++++++-- 13 files changed, 161 insertions(+), 18 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 0770e89..920fd49 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -1780,7 +1780,8 @@ esxDomainSuspend(virDomainPtr domain) static int -esxDomainResume(virDomainPtr domain) +esxDomainResumeFlags(virDomainPtr domain, + unsigned int flags) { int result = -1; esxPrivate *priv = domain->conn->privateData; @@ -1791,6 +1792,8 @@ esxDomainResume(virDomainPtr domain) esxVI_TaskInfoState taskInfoState; char *taskInfoErrorMessage = NULL; + virCheckFlags(0, -1); + if (esxVI_EnsureSession(priv->primary) < 0) { return -1; } @@ -1838,6 +1841,14 @@ esxDomainResume(virDomainPtr domain) static int +esxDomainResume(virDomainPtr domain) +{ + return esxDomainResumeFlags(domain, 0); +} + + + +static int esxDomainShutdownFlags(virDomainPtr domain, unsigned int flags) { int result = -1; @@ -5310,6 +5321,7 @@ static virHypervisorDriver esxDriver = { .domainLookupByName = esxDomainLookupByName, /* 0.7.0 */ .domainSuspend = esxDomainSuspend, /* 0.7.0 */ .domainResume = esxDomainResume, /* 0.7.0 */ + .domainResumeFlags = esxDomainResumeFlags, /* 1.2.11 */ .domainShutdown = esxDomainShutdown, /* 0.7.0 */ .domainShutdownFlags = esxDomainShutdownFlags, /* 0.9.10 */ .domainReboot = esxDomainReboot, /* 0.7.0 */ diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 5ffcb85..f41ed1d 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -569,12 +569,15 @@ hypervDomainSuspend(virDomainPtr domain) static int -hypervDomainResume(virDomainPtr domain) +hypervDomainResumeFlags(virDomainPtr domain, + unsigned int flags) { int result = -1; hypervPrivate *priv = domain->conn->privateData; Msvm_ComputerSystem *computerSystem = NULL; + virCheckFlags(0, -1); + if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) { goto cleanup; } @@ -598,6 +601,14 @@ hypervDomainResume(virDomainPtr domain) static int +hypervDomainResume(virDomainPtr domain) +{ + return hypervDomainResumeFlags(domain, 0); +} + + + +static int hypervDomainDestroyFlags(virDomainPtr domain, unsigned int flags) { int result = -1; @@ -1370,6 +1381,7 @@ static virHypervisorDriver hypervDriver = { .domainLookupByName = hypervDomainLookupByName, /* 0.9.5 */ .domainSuspend = hypervDomainSuspend, /* 0.9.5 */ .domainResume = hypervDomainResume, /* 0.9.5 */ + .domainResumeFlags = hypervDomainResumeFlags, /* 1.2.11 */ .domainDestroy = hypervDomainDestroy, /* 0.9.5 */ .domainDestroyFlags = hypervDomainDestroyFlags, /* 0.9.5 */ .domainGetOSType = hypervDomainGetOSType, /* 0.9.5 */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index d2c077c..1be4074 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -814,7 +814,8 @@ libxlDomainSuspend(virDomainPtr dom) static int -libxlDomainResume(virDomainPtr dom) +libxlDomainResumeFlags(virDomainPtr dom, + unsigned int flags) { libxlDriverPrivatePtr driver = dom->conn->privateData; libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); @@ -823,10 +824,12 @@ libxlDomainResume(virDomainPtr dom) virObjectEventPtr event = NULL; int ret = -1; + virCheckFlags(0, -1); + if (!(vm = libxlDomObjFromDomain(dom))) goto cleanup; - if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0) + if (virDomainResumeFlagsEnsureACL(dom->conn, vm->def) < 0) goto cleanup; if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) @@ -873,6 +876,12 @@ libxlDomainResume(virDomainPtr dom) } static int +libxlDomainResume(virDomainPtr dom) +{ + return libxlDomainResumeFlags(dom, 0); +} + +static int libxlDomainShutdownFlags(virDomainPtr dom, unsigned int flags) { virDomainObjPtr vm; @@ -4750,6 +4759,7 @@ static virHypervisorDriver libxlDriver = { .domainLookupByName = libxlDomainLookupByName, /* 0.9.0 */ .domainSuspend = libxlDomainSuspend, /* 0.9.0 */ .domainResume = libxlDomainResume, /* 0.9.0 */ + .domainResumeFlags = libxlDomainResumeFlags, /* 1.2.11 */ .domainShutdown = libxlDomainShutdown, /* 0.9.0 */ .domainShutdownFlags = libxlDomainShutdownFlags, /* 0.9.10 */ .domainReboot = libxlDomainReboot, /* 0.9.0 */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 6a58d50..18d1942 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3367,7 +3367,9 @@ static int lxcDomainSuspend(virDomainPtr dom) return ret; } -static int lxcDomainResume(virDomainPtr dom) +static int +lxcDomainResumeFlags(virDomainPtr dom, + unsigned int flags) { virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; @@ -3376,12 +3378,14 @@ static int lxcDomainResume(virDomainPtr dom) virLXCDomainObjPrivatePtr priv; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); + virCheckFlags(0, -1); + if (!(vm = lxcDomObjFromDomain(dom))) goto cleanup; priv = vm->privateData; - if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0) + if (virDomainResumeFlagsEnsureACL(dom->conn, vm->def) < 0) goto cleanup; if (!virDomainObjIsActive(vm)) { @@ -3418,6 +3422,12 @@ static int lxcDomainResume(virDomainPtr dom) } static int +lxcDomainResume(virDomainPtr dom) +{ + return lxcDomainResumeFlags(dom, 0); +} + +static int lxcDomainOpenConsole(virDomainPtr dom, const char *dev_name, virStreamPtr st, @@ -5737,6 +5747,7 @@ static virHypervisorDriver lxcDriver = { .domainLookupByName = lxcDomainLookupByName, /* 0.4.2 */ .domainSuspend = lxcDomainSuspend, /* 0.7.2 */ .domainResume = lxcDomainResume, /* 0.7.2 */ + .domainResumeFlags = lxcDomainResumeFlags, /* 1.2.11 */ .domainDestroy = lxcDomainDestroy, /* 0.4.4 */ .domainDestroyFlags = lxcDomainDestroyFlags, /* 0.9.4 */ .domainGetOSType = lxcDomainGetOSType, /* 0.4.2 */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index a0346b4..99cc461 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -633,13 +633,17 @@ static int openvzDomainSuspend(virDomainPtr dom) return ret; } -static int openvzDomainResume(virDomainPtr dom) +static int +openvzDomainResumeFlags(virDomainPtr dom, + unsigned int flags) { struct openvz_driver *driver = dom->conn->privateData; virDomainObjPtr vm; const char *prog[] = {VZCTL, "--quiet", "chkpnt", PROGRAM_SENTINEL, "--resume", NULL}; int ret = -1; + virCheckFlags(0, -1); + openvzDriverLock(driver); vm = virDomainObjListFindByUUID(driver->domains, dom->uuid); openvzDriverUnlock(driver); @@ -673,6 +677,12 @@ static int openvzDomainResume(virDomainPtr dom) } static int +openvzDomainResume(virDomainPtr dom) +{ + return openvzDomainResumeFlags(dom, 0); +} + +static int openvzDomainShutdownFlags(virDomainPtr dom, unsigned int flags) { @@ -2577,6 +2587,7 @@ static virHypervisorDriver openvzDriver = { .domainLookupByName = openvzDomainLookupByName, /* 0.3.1 */ .domainSuspend = openvzDomainSuspend, /* 0.8.3 */ .domainResume = openvzDomainResume, /* 0.8.3 */ + .domainResumeFlags = openvzDomainResumeFlags, /* 1.2.11 */ .domainShutdown = openvzDomainShutdown, /* 0.3.1 */ .domainShutdownFlags = openvzDomainShutdownFlags, /* 0.9.10 */ .domainReboot = openvzDomainReboot, /* 0.3.1 */ diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c index 808dc4a..174ea10 100644 --- a/src/parallels/parallels_driver.c +++ b/src/parallels/parallels_driver.c @@ -1474,14 +1474,22 @@ static int parallelsResume(virDomainObjPtr privdom) } static int -parallelsDomainResume(virDomainPtr domain) +parallelsDomainResumeFlags(virDomainPtr domain, + unsigned int flags) { + virCheckFlags(0, -1); return parallelsDomainChangeState(domain, VIR_DOMAIN_PAUSED, "paused", parallelsResume, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNPAUSED); } +static int +parallelsDomainResume(virDomainPtr domain) +{ + return parallelsDomainResumeFlags(domain, 0); +} + static int parallelsStart(virDomainObjPtr privdom) { return parallelsCmdRun(PRLCTL, "start", PARALLELS_UUID(privdom), NULL); @@ -2490,6 +2498,7 @@ static virHypervisorDriver parallelsDriver = { .domainGetVcpus = parallelsDomainGetVcpus, /* 1.2.6 */ .domainSuspend = parallelsDomainSuspend, /* 0.10.0 */ .domainResume = parallelsDomainResume, /* 0.10.0 */ + .domainResumeFlags = parallelsDomainResumeFlags, /* 1.2.11 */ .domainDestroy = parallelsDomainDestroy, /* 0.10.0 */ .domainShutdown = parallelsDomainShutdown, /* 0.10.0 */ .domainCreate = parallelsDomainCreate, /* 0.10.0 */ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 09617c8..4975d4b 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -3308,7 +3308,8 @@ phypDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) } static int -phypDomainResume(virDomainPtr dom) +phypDomainResumeFlags(virDomainPtr dom, + unsigned int flags) { int result = -1; ConnectionData *connection_data = dom->conn->networkPrivateData; @@ -3320,6 +3321,8 @@ phypDomainResume(virDomainPtr dom) char *ret = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; + virCheckFlags(0, -1); + virBufferAddLit(&buf, "chsysstate"); if (system_type == HMC) virBufferAsprintf(&buf, " -m %s", managed_system); @@ -3339,6 +3342,12 @@ phypDomainResume(virDomainPtr dom) } static int +phypDomainResume(virDomainPtr dom) +{ + return phypDomainResumeFlags(dom, 0); +} + +static int phypDomainReboot(virDomainPtr dom, unsigned int flags) { int result = -1; @@ -3731,6 +3740,7 @@ static virHypervisorDriver phypDriver = { .domainLookupByID = phypDomainLookupByID, /* 0.7.0 */ .domainLookupByName = phypDomainLookupByName, /* 0.7.0 */ .domainResume = phypDomainResume, /* 0.7.0 */ + .domainResumeFlags = phypDomainResumeFlags, /* 1.2.11 */ .domainShutdown = phypDomainShutdown, /* 0.7.0 */ .domainReboot = phypDomainReboot, /* 0.9.1 */ .domainDestroy = phypDomainDestroy, /* 0.7.3 */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 6fc15c0..d6cb404 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1868,7 +1868,9 @@ static int qemuDomainSuspend(virDomainPtr dom) } -static int qemuDomainResume(virDomainPtr dom) +static int +qemuDomainResumeFlags(virDomainPtr dom, + unsigned int flags) { virQEMUDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; @@ -1878,12 +1880,14 @@ static int qemuDomainResume(virDomainPtr dom) virQEMUDriverConfigPtr cfg = NULL; virCapsPtr caps = NULL; + virCheckFlags(0, -1); + if (!(vm = qemuDomObjFromDomain(dom))) return -1; cfg = virQEMUDriverGetConfig(driver); - if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0) + if (virDomainResumeFlagsEnsureACL(dom->conn, vm->def) < 0) goto cleanup; if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) @@ -1933,6 +1937,12 @@ static int qemuDomainResume(virDomainPtr dom) return ret; } +static int +qemuDomainResume(virDomainPtr dom) +{ + return qemuDomainResumeFlags(dom, 0); +} + static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags) { virQEMUDriverPtr driver = dom->conn->privateData; @@ -18619,6 +18629,7 @@ static virHypervisorDriver qemuDriver = { .domainLookupByName = qemuDomainLookupByName, /* 0.2.0 */ .domainSuspend = qemuDomainSuspend, /* 0.2.0 */ .domainResume = qemuDomainResume, /* 0.2.0 */ + .domainResumeFlags = qemuDomainResumeFlags, /* 1.2.11 */ .domainShutdown = qemuDomainShutdown, /* 0.2.0 */ .domainShutdownFlags = qemuDomainShutdownFlags, /* 0.9.10 */ .domainReboot = qemuDomainReboot, /* 0.9.3 */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 2afd6fe..2bc522e 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -1921,13 +1921,17 @@ static int testDomainDestroy(virDomainPtr domain) return ret; } -static int testDomainResume(virDomainPtr domain) +static int +testDomainResumeFlags(virDomainPtr domain, + unsigned int flags) { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; virObjectEventPtr event = NULL; int ret = -1; + virCheckFlags(0, -1); + testDriverLock(privconn); privdom = virDomainObjListFindByName(privconn->domains, domain->name); @@ -1962,6 +1966,12 @@ static int testDomainResume(virDomainPtr domain) return ret; } +static int +testDomainResume(virDomainPtr domain) +{ + return testDomainResumeFlags(domain, 0); +} + static int testDomainSuspend(virDomainPtr domain) { testConnPtr privconn = domain->conn->privateData; @@ -7375,6 +7385,7 @@ static virHypervisorDriver testDriver = { .domainLookupByName = testDomainLookupByName, /* 0.1.1 */ .domainSuspend = testDomainSuspend, /* 0.1.1 */ .domainResume = testDomainResume, /* 0.1.1 */ + .domainResumeFlags = testDomainResumeFlags, /* 1.2.11 */ .domainShutdown = testDomainShutdown, /* 0.1.1 */ .domainShutdownFlags = testDomainShutdownFlags, /* 0.9.10 */ .domainReboot = testDomainReboot, /* 0.1.1 */ diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index bc80338..a7e8516 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2474,7 +2474,8 @@ static int vboxDomainSuspend(virDomainPtr dom) return ret; } -static int vboxDomainResume(virDomainPtr dom) +static int vboxDomainResumeFlags(virDomainPtr dom, + unsigned int flags) { vboxGlobalData *data = dom->conn->privateData; IMachine *machine = NULL; @@ -2484,6 +2485,8 @@ static int vboxDomainResume(virDomainPtr dom) PRBool isAccessible = PR_FALSE; int ret = -1; + virCheckFlags(0, -1); + if (!data->vboxObj) return ret; @@ -2525,6 +2528,11 @@ static int vboxDomainResume(virDomainPtr dom) return ret; } +static int vboxDomainResume(virDomainPtr dom) +{ + return vboxDomainResumeFlags(dom, 0); +} + static int vboxDomainShutdownFlags(virDomainPtr dom, unsigned int flags) { vboxGlobalData *data = dom->conn->privateData; @@ -7617,6 +7625,7 @@ virHypervisorDriver vboxCommonDriver = { .domainLookupByName = vboxDomainLookupByName, /* 0.6.3 */ .domainSuspend = vboxDomainSuspend, /* 0.6.3 */ .domainResume = vboxDomainResume, /* 0.6.3 */ + .domainResumeFlags = vboxDomainResumeFlags, /* 1.2.11 */ .domainShutdown = vboxDomainShutdown, /* 0.6.3 */ .domainShutdownFlags = vboxDomainShutdownFlags, /* 0.9.10 */ .domainReboot = vboxDomainReboot, /* 0.6.3 */ diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index c3fa2dc..82bcbc9 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -543,7 +543,8 @@ vmwareDomainSuspend(virDomainPtr dom) } static int -vmwareDomainResume(virDomainPtr dom) +vmwareDomainResumeFlags(virDomainPtr dom, + unsigned int flags) { struct vmware_driver *driver = dom->conn->privateData; @@ -554,6 +555,8 @@ vmwareDomainResume(virDomainPtr dom) }; int ret = -1; + virCheckFlags(0, -1); + if (driver->type == VMWARE_DRIVER_PLAYER) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("vmplayer does not support libvirt suspend/resume " @@ -592,6 +595,12 @@ vmwareDomainResume(virDomainPtr dom) } static int +vmwareDomainResume(virDomainPtr dom) +{ + return vmwareDomainResumeFlags(dom, 0); +} + +static int vmwareDomainReboot(virDomainPtr dom, unsigned int flags) { struct vmware_driver *driver = dom->conn->privateData; @@ -1198,6 +1207,7 @@ static virHypervisorDriver vmwareDriver = { .domainLookupByName = vmwareDomainLookupByName, /* 0.8.7 */ .domainSuspend = vmwareDomainSuspend, /* 0.8.7 */ .domainResume = vmwareDomainResume, /* 0.8.7 */ + .domainResumeFlags = vmwareDomainResumeFlags, /* 1.2.11 */ .domainShutdown = vmwareDomainShutdown, /* 0.8.7 */ .domainShutdownFlags = vmwareDomainShutdownFlags, /* 0.9.10 */ .domainReboot = vmwareDomainReboot, /* 0.8.7 */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 5f7c98f..4fec3a2 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -949,15 +949,18 @@ xenUnifiedDomainSuspend(virDomainPtr dom) } static int -xenUnifiedDomainResume(virDomainPtr dom) +xenUnifiedDomainResumeFlags(virDomainPtr dom, + unsigned int flags) { int ret = -1; virDomainDefPtr def; + virCheckFlags(0, -1); + if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; - if (virDomainResumeEnsureACL(dom->conn, def) < 0) + if (virDomainResumeFlagsEnsureACL(dom->conn, def) < 0) goto cleanup; ret = xenDaemonDomainResume(dom->conn, def); @@ -968,6 +971,12 @@ xenUnifiedDomainResume(virDomainPtr dom) } static int +xenUnifiedDomainResume(virDomainPtr dom) +{ + return xenUnifiedDomainResumeFlags(dom, 0); +} + +static int xenUnifiedDomainShutdownFlags(virDomainPtr dom, unsigned int flags) { @@ -2765,6 +2774,7 @@ static virHypervisorDriver xenUnifiedDriver = { .domainLookupByName = xenUnifiedDomainLookupByName, /* 0.0.3 */ .domainSuspend = xenUnifiedDomainSuspend, /* 0.0.3 */ .domainResume = xenUnifiedDomainResume, /* 0.0.3 */ + .domainResumeFlags = xenUnifiedDomainResumeFlags, /* 1.2.11 */ .domainShutdown = xenUnifiedDomainShutdown, /* 0.0.3 */ .domainShutdownFlags = xenUnifiedDomainShutdownFlags, /* 0.9.10 */ .domainReboot = xenUnifiedDomainReboot, /* 0.1.0 */ diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index ed4f7e8..73257cc 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -766,18 +766,22 @@ xenapiDomainSuspend(virDomainPtr dom) } /* - * xenapiDomainResume + * xenapiDomainResumeFlags * * Resumes a VM * Returns 0 on success or -1 in case of error */ static int -xenapiDomainResume(virDomainPtr dom) +xenapiDomainResumeFlags(virDomainPtr dom, + unsigned int flags) { /* vm.unpause() */ xen_vm vm; xen_vm_set *vms; xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; + + virCheckFlags(0, -1); + if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) { if (vms->size != 1) { xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, @@ -802,6 +806,18 @@ xenapiDomainResume(virDomainPtr dom) } /* + * xenapiDomainResume + * + * Resumes a VM + * Returns 0 on success or -1 in case of error + */ +static int +xenapiDomainResume(virDomainPtr dom) +{ + return xenapiDomainResumeFlags(dom, 0); +} + +/* * xenapiDomainShutdown * * shutsdown a VM @@ -1983,6 +1999,7 @@ static virHypervisorDriver xenapiDriver = { .domainLookupByName = xenapiDomainLookupByName, /* 0.8.0 */ .domainSuspend = xenapiDomainSuspend, /* 0.8.0 */ .domainResume = xenapiDomainResume, /* 0.8.0 */ + .domainResumeFlags = xenapiDomainResumeFlags, /* 1.2.11 */ .domainShutdown = xenapiDomainShutdown, /* 0.8.0 */ .domainShutdownFlags = xenapiDomainShutdownFlags, /* 0.9.10 */ .domainReboot = xenapiDomainReboot, /* 0.8.0 */ -- 2.0.4

On 11/06/14 14:01, Michal Privoznik wrote:
This practically boils down to: 1) rename DomainResume implementation to DomainResumeFlags 2) make DomainResume call DomainResumeFlags(dom, 0);
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/esx/esx_driver.c | 14 +++++++++++++- src/hyperv/hyperv_driver.c | 14 +++++++++++++- src/libxl/libxl_driver.c | 14 ++++++++++++-- src/lxc/lxc_driver.c | 15 +++++++++++++-- src/openvz/openvz_driver.c | 13 ++++++++++++- src/parallels/parallels_driver.c | 11 ++++++++++- src/phyp/phyp_driver.c | 12 +++++++++++- src/qemu/qemu_driver.c | 15 +++++++++++++-- src/test/test_driver.c | 13 ++++++++++++- src/vbox/vbox_common.c | 11 ++++++++++- src/vmware/vmware_driver.c | 12 +++++++++++- src/xen/xen_driver.c | 14 ++++++++++++-- src/xenapi/xenapi_driver.c | 21 +++++++++++++++++++-- 13 files changed, 161 insertions(+), 18 deletions(-)
ACK, Peter

This is pure code movement to dig out the function internals into a separate functions as the code is to be reused later. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_driver.c | 86 +++++++++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 32 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d6cb404..7065999 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1868,6 +1868,59 @@ static int qemuDomainSuspend(virDomainPtr dom) } +/** + * qemuDomainSetTimeImpl: + * + * Domain must have a job set as the monitor is entered here. + * + * Returns 0 on success, -1 otherwise. + */ +static int +qemuDomainSetTimeImpl(virQEMUDriverPtr driver, + virDomainObjPtr vm, + long long seconds, + unsigned int nseconds, + bool rtcSync) +{ + int rv, ret = -1; + qemuDomainObjPrivatePtr priv = vm->privateData; + + if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_RTC_RESET_REINJECTION)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("cannot set time: qemu doesn't support " + "rtc-reset-reinjection command")); + goto cleanup; + } + + if (!qemuDomainAgentAvailable(priv, true)) + goto cleanup; + + qemuDomainObjEnterAgent(vm); + rv = qemuAgentSetTime(priv->agent, seconds, nseconds, rtcSync); + qemuDomainObjExitAgent(vm); + + if (rv < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) { + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto cleanup; + } + + qemuDomainObjEnterMonitor(driver, vm); + rv = qemuMonitorRTCResetReinjection(priv->mon); + qemuDomainObjExitMonitor(driver, vm); + + if (rv < 0) + goto cleanup; + + ret = 0; + cleanup: + return ret; +} + + static int qemuDomainResumeFlags(virDomainPtr dom, unsigned int flags) @@ -17712,11 +17765,9 @@ qemuDomainSetTime(virDomainPtr dom, unsigned int flags) { virQEMUDriverPtr driver = dom->conn->privateData; - qemuDomainObjPrivatePtr priv; virDomainObjPtr vm; bool rtcSync = flags & VIR_DOMAIN_TIME_SYNC; int ret = -1; - int rv; virCheckFlags(VIR_DOMAIN_TIME_SYNC, ret); @@ -17726,8 +17777,6 @@ qemuDomainSetTime(virDomainPtr dom, if (virDomainSetTimeEnsureACL(dom->conn, vm->def) < 0) goto cleanup; - priv = vm->privateData; - if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; @@ -17737,34 +17786,7 @@ qemuDomainSetTime(virDomainPtr dom, goto endjob; } - if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_RTC_RESET_REINJECTION)) { - virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", - _("cannot set time: qemu doesn't support " - "rtc-reset-reinjection command")); - goto endjob; - } - - if (!qemuDomainAgentAvailable(priv, true)) - goto endjob; - - qemuDomainObjEnterAgent(vm); - rv = qemuAgentSetTime(priv->agent, seconds, nseconds, rtcSync); - qemuDomainObjExitAgent(vm); - - if (rv < 0) - goto endjob; - - if (!virDomainObjIsActive(vm)) { - virReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("domain is not running")); - goto endjob; - } - - qemuDomainObjEnterMonitor(driver, vm); - rv = qemuMonitorRTCResetReinjection(priv->mon); - qemuDomainObjExitMonitor(driver, vm); - - if (rv < 0) + if (qemuDomainSetTimeImpl(driver, vm, seconds, nseconds, rtcSync) < 0) goto endjob; ret = 0; -- 2.0.4

On 11/06/14 14:01, Michal Privoznik wrote:
This is pure code movement to dig out the function internals into a separate functions as the code is to be reused later.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_driver.c | 86 +++++++++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 32 deletions(-)
ACK, Peter

This flag can be used to sync the domain's time right after domain CPUs are started. It's basically backing call of two subsequent APIs into one: 1) virDomainResume(dom) 2) virDomainSetTime(dom, 0, 0, VIR_DOMAIN_TIME_SYNC) Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- include/libvirt/libvirt-domain.h | 7 +++++++ src/libvirt-domain.c | 18 ++++++++++++------ src/qemu/qemu_driver.c | 20 +++++++++++++++++++- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 1795dd3..faafee4 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -867,6 +867,13 @@ int virDomainFree (virDomainPtr domain); /* * Domain suspend/resume */ +typedef enum { + VIR_DOMAIN_RESUME_SYNC_TIME = 1 << 0, /* On resume sync domain time from + its RTC. Depending on underlying + hypervisor it may require guest + agent. */ +} virDomainResumeFlagsValues; + int virDomainSuspend (virDomainPtr domain); int virDomainResume (virDomainPtr domain); int virDomainResumeFlags (virDomainPtr domain, diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 7d21d77..7c8ccd8 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -695,13 +695,19 @@ virDomainResume(virDomainPtr domain) /** * virDomainResumeFlags: * @domain: a domain object - * @flags: extra flags; not used yet, so callers should always pass 0 + * @flags: bitwise-OR of virDomainResumeFlagsValues * - * Resume a suspended domain, the process is restarted from the state where - * it was frozen by calling virDomainSuspend(). - * This function may require privileged access - * Moreover, resume may not be supported if domain is in some - * special state like VIR_DOMAIN_PMSUSPENDED. + * Resume a suspended domain, the process is restarted from the + * state where it was frozen by calling virDomainSuspend(). This + * function may require privileged access Moreover, resume may + * not be supported if domain is in some special state like + * VIR_DOMAIN_PMSUSPENDED. If VIR_DOMAIN_RESUME_SYNC_TIME flag + * is specified the domain's time is synced once its vCPUs are + * started. Depending on driver, this flag may require guest + * agent. However, due to nature of things in such drivers, vCPUs + * may have executed some instructions prior the time is set. + * Moreover, if time synchronisation fails, domain remains + * resumed, so you should check the domain state on error. * * Returns 0 in case of success and -1 in case of failure. */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7065999..342d630 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1933,7 +1933,7 @@ qemuDomainResumeFlags(virDomainPtr dom, virQEMUDriverConfigPtr cfg = NULL; virCapsPtr caps = NULL; - virCheckFlags(0, -1); + virCheckFlags(VIR_DOMAIN_RESUME_SYNC_TIME, -1); if (!(vm = qemuDomObjFromDomain(dom))) return -1; @@ -1974,6 +1974,24 @@ qemuDomainResumeFlags(virDomainPtr dom, goto endjob; if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) goto endjob; + + if (flags & VIR_DOMAIN_RESUME_SYNC_TIME) { + if (!virDomainObjIsActive(vm)) { + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto endjob; + } + + if (qemuDomainSetTimeImpl(driver, vm, 0, 0, true) < 0) { + /* Intentionally overwrite the error, to make it + * obvious that guest is running. */ + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("domain resumed, but time " + "synchronization failed!")); + goto endjob; + } + } + ret = 0; endjob: -- 2.0.4

On 11/06/2014 02:01 PM, Michal Privoznik wrote:
This flag can be used to sync the domain's time right after domain CPUs are started. It's basically backing call of two subsequent APIs into one:
1) virDomainResume(dom) 2) virDomainSetTime(dom, 0, 0, VIR_DOMAIN_TIME_SYNC)
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- include/libvirt/libvirt-domain.h | 7 +++++++ src/libvirt-domain.c | 18 ++++++++++++------ src/qemu/qemu_driver.c | 20 +++++++++++++++++++-
Still missing a change to remote_protocol.x to add proper ACL checking of the flag (see my reply to v1). -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 06.11.2014 15:31, Eric Blake wrote:
On 11/06/2014 02:01 PM, Michal Privoznik wrote:
This flag can be used to sync the domain's time right after domain CPUs are started. It's basically backing call of two subsequent APIs into one:
1) virDomainResume(dom) 2) virDomainSetTime(dom, 0, 0, VIR_DOMAIN_TIME_SYNC)
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- include/libvirt/libvirt-domain.h | 7 +++++++ src/libvirt-domain.c | 18 ++++++++++++------ src/qemu/qemu_driver.c | 20 +++++++++++++++++++-
Still missing a change to remote_protocol.x to add proper ACL checking of the flag (see my reply to v1).
Okay, fixed in my local branch. Any other comments? Michal

On 11/12/14 18:40, Michal Privoznik wrote:
On 06.11.2014 15:31, Eric Blake wrote:
On 11/06/2014 02:01 PM, Michal Privoznik wrote:
This flag can be used to sync the domain's time right after domain CPUs are started. It's basically backing call of two subsequent APIs into one:
1) virDomainResume(dom) 2) virDomainSetTime(dom, 0, 0, VIR_DOMAIN_TIME_SYNC)
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- include/libvirt/libvirt-domain.h | 7 +++++++ src/libvirt-domain.c | 18 ++++++++++++------ src/qemu/qemu_driver.c | 20 +++++++++++++++++++-
Still missing a change to remote_protocol.x to add proper ACL checking of the flag (see my reply to v1).
Okay, fixed in my local branch. Any other comments?
For this one I'm still not convinced this is a good idea to combine the two operations. I'd still like to have a second opinion on that. Code-wise you've solved all my requests from the previous version. 1/2 ACK. Peter

This is done by introducing '--sync-time' to already existing 'resume' command. If the option is used, the newer Flags() API is called. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain.c | 13 ++++++++++++- tools/virsh.pod | 11 +++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index bd5f404..d264cd9 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -5135,6 +5135,10 @@ static const vshCmdOptDef opts_resume[] = { .flags = VSH_OFLAG_REQ, .help = N_("domain name, id or uuid") }, + {.name = "sync-time", + .type = VSH_OT_BOOL, + .help = N_("sync domain's time from its RTC") + }, {.name = NULL} }; @@ -5144,11 +5148,18 @@ cmdResume(vshControl *ctl, const vshCmd *cmd) virDomainPtr dom; bool ret = true; const char *name; + unsigned int flags = 0; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) return false; - if (virDomainResume(dom) == 0) { + if (vshCommandOptBool(cmd, "sync-time")) + flags |= VIR_DOMAIN_RESUME_SYNC_TIME; + + if ((flags && + virDomainResumeFlags(dom, flags) == 0) || + (!flags && + virDomainResume(dom) == 0)) { vshPrint(ctl, _("Domain %s resumed\n"), name); } else { vshError(ctl, _("Failed to resume domain %s"), name); diff --git a/tools/virsh.pod b/tools/virsh.pod index daddb48..faa5928 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -2101,11 +2101,14 @@ is only supported with container based virtualization. Suspend a running domain. It is kept in memory but won't be scheduled anymore. -=item B<resume> I<domain> +=item B<resume> I<domain> [I<--sync-time>] -Moves a domain out of the suspended state. This will allow a previously -suspended domain to now be eligible for scheduling by the underlying -hypervisor. +Moves a domain out of the suspended state. This will allow a +previously suspended domain to now be eligible for scheduling by the +underlying hypervisor. Moreover, if I<--sync-time> is specified the +domain's time is synced after the domain CPUs are started. Note, that +this may require guest agent on some hypervisors and thus creates a +window where some instructions can be executed with old time. =item B<dompmsuspend> I<domain> I<target> [I<--duration>] -- 2.0.4

On 11/06/14 14:01, Michal Privoznik wrote:
This is done by introducing '--sync-time' to already existing 'resume' command. If the option is used, the newer Flags() API is called.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain.c | 13 ++++++++++++- tools/virsh.pod | 11 +++++++---- 2 files changed, 19 insertions(+), 5 deletions(-)
ACK, Peter

On 06.11.2014 14:01, Michal Privoznik wrote:
Diff to v1: -Fixed issues raised by Peter
Michal Privoznik (5): Introduce virDomainResumeFlags API Implement virDomainResumeFlags in all drivers qemu: Split qemuDomainSetTime into two functions qemuDomainResumeFlags: Introduce VIR_DOMAIN_RESUME_SYNC_TIME virsh: Implement virDomainResumeFlags
include/libvirt/libvirt-domain.h | 9 +++ src/driver-hypervisor.h | 5 ++ src/esx/esx_driver.c | 14 ++++- src/hyperv/hyperv_driver.c | 14 ++++- src/libvirt-domain.c | 50 ++++++++++++++++ src/libvirt_public.syms | 5 ++ src/libxl/libxl_driver.c | 14 ++++- src/lxc/lxc_driver.c | 15 ++++- src/openvz/openvz_driver.c | 13 ++++- src/parallels/parallels_driver.c | 11 +++- src/phyp/phyp_driver.c | 12 +++- src/qemu/qemu_driver.c | 119 ++++++++++++++++++++++++++++----------- src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 13 ++++- src/remote_protocol-structs | 5 ++ src/test/test_driver.c | 13 ++++- src/vbox/vbox_common.c | 11 +++- src/vmware/vmware_driver.c | 12 +++- src/xen/xen_driver.c | 14 ++++- src/xenapi/xenapi_driver.c | 21 ++++++- tools/virsh-domain.c | 13 ++++- tools/virsh.pod | 11 ++-- 22 files changed, 339 insertions(+), 56 deletions(-)
Ping?
participants (3)
-
Eric Blake
-
Michal Privoznik
-
Peter Krempa