diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 5605a94969..5b80b85246 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -4102,4 +4102,9 @@ int virDomainGetGuestVcpus(virDomainPtr domain, unsigned int *nparams, unsigned int flags); +int virDomainSetGuestVcpus(virDomainPtr domain, + const char *cpumap, + int state, + unsigned int flags); + #endif /* __VIR_LIBVIRT_DOMAIN_H__ */ diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index 93af2b664e..5cd1fdf4f3 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -1245,6 +1245,12 @@ typedef int unsigned int *nparams, unsigned int flags); +typedef int +(*virDrvDomainSetGuestVcpus)(virDomainPtr domain, + const char *cpumap, + int state, + unsigned int flags); + typedef struct _virHypervisorDriver virHypervisorDriver; typedef virHypervisorDriver *virHypervisorDriverPtr; @@ -1482,6 +1488,7 @@ struct _virHypervisorDriver { virDrvConnectUnregisterCloseCallback connectUnregisterCloseCallback; virDrvDomainMigrateStartPostCopy domainMigrateStartPostCopy; virDrvDomainGetGuestVcpus domainGetGuestVcpus; + virDrvDomainSetGuestVcpus domainSetGuestVcpus; }; diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index eb995b570f..508520efd6 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11891,3 +11891,58 @@ virDomainGetGuestVcpus(virDomainPtr domain, virDispatchError(domain->conn); return -1; } + + +/** + * virDomainSetGuestVcpus: + * @domain: pointer to domain object + * @cpumap: text representation of a bitmap of vcpus to set + * @state: 0 to disable/1 to enable cpus described by @cpumap + * @flags: currently unused, callers shall pass 0 + * + * Sets state of individual vcpus described by @cpumap via guest agent. Other + * vcpus are not modified. + * + * This API requires the VM to run. Various hypervisors or guest agent + * implementation may limit to operate on just 1 vCPU per call. + * + * @cpumap is a list of vCPU numbers. Its syntax is a comma separated list and + * a special markup using '-' and '^' (ex. '0-4', '0-3,^2'). The '-' denotes + * the range and the '^' denotes exclusive. The expression is sequentially + * evaluated, so "0-15,^8" is identical to "9-14,0-7,15" but not identical to + * "^8,0-15". + * + * Note that OSes (notably Linux) may require vCPU 0 to stay online to support + * low-level features a S3 sleep. + * + * Returns 0 on success, -1 on error. + */ +int +virDomainSetGuestVcpus(virDomainPtr domain, + const char *cpumap, + int state, + unsigned int flags) +{ + VIR_DOMAIN_DEBUG(domain, "cpumap='%s' state=%x flags=%x", + NULLSTR(cpumap), state, flags); + + virResetLastError(); + + virCheckDomainReturn(domain, -1); + virCheckNonNullArgGoto(cpumap, error); + + if (domain->conn->driver->domainSetGuestVcpus) { + int ret; + ret = domain->conn->driver->domainSetGuestVcpus(domain, cpumap, state, + flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(domain->conn); + return -1; +} diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 30801c5a54..b6d2dfdba3 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -737,6 +737,7 @@ LIBVIRT_2.0.0 { virConnectStoragePoolEventRegisterAny; virConnectStoragePoolEventDeregisterAny; virDomainGetGuestVcpus; + virDomainSetGuestVcpus; } LIBVIRT_1.3.3; # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 6a580c6c01..3f9d812fc9 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -7982,6 +7982,7 @@ static virHypervisorDriver hypervisor_driver = { .connectUnregisterCloseCallback = remoteConnectUnregisterCloseCallback, /* 1.3.2 */ .domainMigrateStartPostCopy = remoteDomainMigrateStartPostCopy, /* 1.3.3 */ .domainGetGuestVcpus = remoteDomainGetGuestVcpus, /* 2.0.0 */ + .domainSetGuestVcpus = remoteDomainSetGuestVcpus, /* 2.0.0 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index f72918d2e3..d11bfdf699 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3304,6 +3304,13 @@ struct remote_domain_get_guest_vcpus_ret { remote_typed_param params; /* alloc@1@unsigned int@2 */ }; +struct remote_domain_set_guest_vcpus_args { + remote_nonnull_domain dom; + remote_nonnull_string cpumap; + int state; + unsigned int flags; +}; + /*----- Protocol. -----*/ @@ -5858,5 +5865,11 @@ enum remote_procedure { * @generate: both * @acl: domain:write */ - REMOTE_PROC_DOMAIN_GET_GUEST_VCPUS = 371 + REMOTE_PROC_DOMAIN_GET_GUEST_VCPUS = 371, + + /** + * @generate: both + * @acl: domain:write + */ + REMOTE_PROC_DOMAIN_SET_GUEST_VCPUS = 372 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 4e603dbe52..0d89b15c21 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2761,6 +2761,12 @@ struct remote_domain_get_guest_vcpus_ret { remote_typed_param * params_val; } params; }; +struct remote_domain_set_guest_vcpus_args { + remote_nonnull_domain dom; + remote_nonnull_string cpumap; + int state; + u_int flags; +}; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN = 1, REMOTE_PROC_CONNECT_CLOSE = 2, @@ -3133,4 +3139,5 @@ enum remote_procedure { REMOTE_PROC_CONNECT_STORAGE_POOL_EVENT_DEREGISTER_ANY = 369, REMOTE_PROC_STORAGE_POOL_EVENT_LIFECYCLE = 370, REMOTE_PROC_DOMAIN_GET_GUEST_VCPUS = 371, + REMOTE_PROC_DOMAIN_SET_GUEST_VCPUS = 372, };