diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index e303140a23..c0f715d66a 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -4528,4 +4528,9 @@ int virDomainSetGuestVcpus(virDomainPtr domain, int state, unsigned int flags); +int virDomainSetVcpu(virDomainPtr domain, + const char *vcpumap, + int state, + unsigned int flags); + #endif /* __VIR_LIBVIRT_DOMAIN_H__ */ diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index 51af73200b..b81420aefe 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -1251,6 +1251,12 @@ typedef int int state, unsigned int flags); +typedef int +(*virDrvDomainSetVcpu)(virDomainPtr domain, + const char *cpumap, + int state, + unsigned int flags); + typedef struct _virHypervisorDriver virHypervisorDriver; typedef virHypervisorDriver *virHypervisorDriverPtr; @@ -1489,6 +1495,7 @@ struct _virHypervisorDriver { virDrvDomainMigrateStartPostCopy domainMigrateStartPostCopy; virDrvDomainGetGuestVcpus domainGetGuestVcpus; virDrvDomainSetGuestVcpus domainSetGuestVcpus; + virDrvDomainSetVcpu domainSetVcpu; }; diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 5b3e842058..619a9fccb2 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11749,3 +11749,51 @@ virDomainSetGuestVcpus(virDomainPtr domain, virDispatchError(domain->conn); return -1; } + + +/** + * virDomainSetVcpu: + * @domain: pointer to domain object + * @vcpumap: text representation of a bitmap of vcpus to set + * @state: 0 to disable/1 to enable cpus described by @vcpumap + * @flags: bitwise-OR of virDomainModificationImpact + * + * Enables/disables individual vcpus described by @vcpumap in the hypervisor. + * + * Various hypervisor implementations may limit to operate on just 1 + * hotpluggable entity (which may contain multiple vCPUs on certain platforms). + * + * Note that OSes and hypervisors may require vCPU 0 to stay online. + * + * Returns 0 on success, -1 on error. + */ +int +virDomainSetVcpu(virDomainPtr domain, + const char *vcpumap, + int state, + unsigned int flags) +{ + VIR_DOMAIN_DEBUG(domain, "vcpumap='%s' state=%i flags=%x", + NULLSTR(vcpumap), state, flags); + + virResetLastError(); + + virCheckDomainReturn(domain, -1); + virCheckReadOnlyGoto(domain->conn->flags, error); + + virCheckNonNullArgGoto(vcpumap, error); + + if (domain->conn->driver->domainSetVcpu) { + int ret; + ret = domain->conn->driver->domainSetVcpu(domain, vcpumap, 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 62885ac415..04ef58021b 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -753,4 +753,9 @@ LIBVIRT_3.0.0 { virConnectSecretEventDeregisterAny; } LIBVIRT_2.2.0; +LIBVIRT_3.1.0 { + global: + virDomainSetVcpu; +} LIBVIRT_3.0.0; + # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index a3f7d9b0ba..0c8bfeed16 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -8402,6 +8402,7 @@ static virHypervisorDriver hypervisor_driver = { .domainMigrateStartPostCopy = remoteDomainMigrateStartPostCopy, /* 1.3.3 */ .domainGetGuestVcpus = remoteDomainGetGuestVcpus, /* 2.0.0 */ .domainSetGuestVcpus = remoteDomainSetGuestVcpus, /* 2.0.0 */ + .domainSetVcpu = remoteDomainSetVcpu, /* 3.1.0 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index cd0a14cc69..abe63af070 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3353,6 +3353,13 @@ struct remote_domain_set_guest_vcpus_args { unsigned int flags; }; +struct remote_domain_set_vcpu_args { + remote_nonnull_domain dom; + remote_nonnull_string cpumap; + int state; + unsigned int flags; +}; + struct remote_domain_event_callback_metadata_change_msg { int callbackID; @@ -6018,6 +6025,13 @@ enum remote_procedure { * @generate: both * @acl: none */ - REMOTE_PROC_SECRET_EVENT_VALUE_CHANGED = 383 + REMOTE_PROC_SECRET_EVENT_VALUE_CHANGED = 383, + /** + * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG + */ + REMOTE_PROC_DOMAIN_SET_VCPU = 384 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 0360600cfb..e1e53d21b2 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2800,6 +2800,12 @@ struct remote_domain_set_guest_vcpus_args { int state; u_int flags; }; +struct remote_domain_set_vcpu_args { + remote_nonnull_domain dom; + remote_nonnull_string cpumap; + int state; + u_int flags; +}; struct remote_domain_event_callback_metadata_change_msg { int callbackID; remote_nonnull_domain dom; @@ -3210,4 +3216,5 @@ enum remote_procedure { REMOTE_PROC_CONNECT_SECRET_EVENT_DEREGISTER_ANY = 381, REMOTE_PROC_SECRET_EVENT_LIFECYCLE = 382, REMOTE_PROC_SECRET_EVENT_VALUE_CHANGED = 383, + REMOTE_PROC_DOMAIN_SET_VCPU = 384, };