[PATCH] Add support for libvirt CPU cgroup for active KVM guests

# HG changeset patch # User Gareth S. Bestor <bestor@us.ibm.com> # Date 1317635486 25200 # Node ID 2c9a378e141c23eae0b96b2f021adbd14cfb8ef2 # Parent fb09136deb494008eb3aacee420ad74da7d7c294 Add support for libvirt CPU cgroup for active KVM guests Add support for setting and retreiving the CPU cgroup setting for an active KVM guest using libivirt scheduling parameter support. Presently this patches only supports earlier libvirt versions' support of this feature, which only support setting these scheduling params for *active* guests only, and uses libivrt's earlier scheduling APIs; a subsequent patch will support both and the newer APIs (version dependent). A guest's CPU cgroup setting it exposed via the KVM_ProcResourceAllocationSettingData.Weight property. Minimum, maximum, Increment and Default weights are exposed appropriately via the respective Processor pool. Weight for new guest can be passed in on DefineSystem[] Weigh for existing (active) guest can be changed via ModifyResourceSettings[] Signed-off-by: Gareth S. Bestor <bestor@us.bm.com> diff -r fb09136deb49 -r 2c9a378e141c libxkutil/device_parsing.c --- a/libxkutil/device_parsing.c Tue Aug 30 08:48:36 2011 -0700 +++ b/libxkutil/device_parsing.c Mon Oct 03 02:51:26 2011 -0700 @@ -1297,6 +1297,24 @@ { int ret; + /* Change vcpu cgroup cpu_shares */ + if (dev->dev.vcpu.weight > 0) { + virSchedParameter param; + + strncpy(param.field, "cpu_shares", VIR_DOMAIN_SCHED_FIELD_LENGTH); + param.type = VIR_DOMAIN_SCHED_FIELD_ULLONG; + param.value.ul = dev->dev.vcpu.weight; + + if (virDomainSetSchedulerParameters(dom, ¶m, 1) != 0) { + CU_DEBUG("Failed to set scheduler params for domain"); + return 0; + } + + CU_DEBUG("Changed %s vcpu cgroup cpu_shares to %i", + virDomainGetName(dom), + dev->dev.vcpu.weight); + } + if (dev->dev.vcpu.quantity <= 0) { CU_DEBUG("Unable to set VCPU count to %i", dev->dev.vcpu.quantity); diff -r fb09136deb49 -r 2c9a378e141c src/Virt_ComputerSystem.c --- a/src/Virt_ComputerSystem.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_ComputerSystem.c Mon Oct 03 02:51:26 2011 -0700 @@ -858,6 +858,30 @@ return 0; } +static int kvm_scheduler_params(struct infostore_ctx *ctx, + virSchedParameter **params) +{ + unsigned long long value; + + *params = calloc(1, sizeof(virSchedParameter)); + if (*params == NULL) + return -1; + + value = infostore_get_u64(ctx, "weight"); + + if (value != 0) { + strncpy((*params)[0].field, + "cpu_shares", + VIR_DOMAIN_SCHED_FIELD_LENGTH); + (*params)[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG; + (*params)[0].value.ul = value; + + return 1; + } + + return 0; +} + static void set_scheduler_params(virDomainPtr dom) { struct infostore_ctx *ctx; @@ -881,6 +905,8 @@ count = xen_scheduler_params(ctx, ¶ms); else if (STREQC(virConnectGetType(conn), "lxc")) count = lxc_scheduler_params(ctx, ¶ms); + else if (STREQC(virConnectGetType(conn), "QEMU")) + count = kvm_scheduler_params(ctx, ¶ms); else { CU_DEBUG("Not setting sched params for type %s", virConnectGetType(conn)); diff -r fb09136deb49 -r 2c9a378e141c src/Virt_RASD.c --- a/src/Virt_RASD.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_RASD.c Mon Oct 03 02:51:26 2011 -0700 @@ -110,7 +110,7 @@ virConnectPtr conn = NULL; virDomainPtr dom = NULL; struct infostore_ctx *info = NULL; - uint32_t weight; + uint32_t weight = 0; uint64_t limit; uint64_t count; @@ -147,7 +147,45 @@ goto out; } - weight = (uint32_t)infostore_get_u64(info, "weight"); + /* Currently only support CPU cgroups for running KVM guests */ + if (domain_online(dom) && STREQC(virConnectGetType(conn), "QEMU")) { + char *sched; + int nparams; + unsigned int i; + virSchedParameter *params; + + /* First find the number of scheduler params, in order malloc space for them all */ + sched = virDomainGetSchedulerType(dom, &nparams); + if (sched == NULL) { + CU_DEBUG("Failed to get scheduler type"); + goto out; + } + CU_DEBUG("domain has %d scheduler params", nparams); + free(sched); + + /* Now retrieve all the scheduler params for this domain */ + params = calloc(nparams, sizeof(virSchedParameter)); + if (virDomainGetSchedulerParameters(dom, params, &nparams) != 0) { + CU_DEBUG("Failed to get scheduler params for domain"); + goto out; + } + + /* Look for the CPU cgroup scheduler parameter, called 'cpu_shares' */ + for (i = 0 ; i < nparams ; i++) { + CU_DEBUG("scheduler param #%d name is %s (type %d)", + i, params[i].field, params[i].type); + if (STREQ(params[i].field, "cpu_shares") && + (params[i].type == VIR_DOMAIN_SCHED_FIELD_ULLONG)) { + CU_DEBUG("scheduler param %s = %d", + params[i].field, params[i].value.ul); + weight = (uint32_t)params[i].value.ul; + break; /* Found it! */ + } + } + free(params); + } + else + weight = (uint32_t)infostore_get_u64(info, "weight"); limit = infostore_get_u64(info, "limit"); CMSetProperty(inst, "Weight", diff -r fb09136deb49 -r 2c9a378e141c src/Virt_SettingsDefineCapabilities.c --- a/src/Virt_SettingsDefineCapabilities.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_SettingsDefineCapabilities.c Mon Oct 03 02:51:26 2011 -0700 @@ -410,7 +410,10 @@ case SDC_RASD_MIN: num_procs = 0; limit = 1; - weight = MIN_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = MIN_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = MIN_KVM_WEIGHT; id = "Minimum"; break; case SDC_RASD_MAX: @@ -418,19 +421,28 @@ if (!ret) goto out; limit = 0; - weight = MAX_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = MAX_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = MAX_KVM_WEIGHT; id = "Maximum"; break; case SDC_RASD_INC: num_procs = 1; limit = 50; - weight = INC_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = INC_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = INC_KVM_WEIGHT; id = "Increment"; break; case SDC_RASD_DEF: num_procs = 1; limit = 0; - weight = DEFAULT_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = DEFAULT_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = DEFAULT_KVM_WEIGHT; id = "Default"; break; default: @@ -455,6 +467,10 @@ CMSetProperty(inst, "Weight", (CMPIValue *)&weight, CMPI_uint32); } + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) { + CMSetProperty(inst, "Weight", + (CMPIValue *)&weight, CMPI_uint32); + } inst_list_add(list, inst); diff -r fb09136deb49 -r 2c9a378e141c src/Virt_VirtualSystemManagementService.c --- a/src/Virt_VirtualSystemManagementService.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_VirtualSystemManagementService.c Mon Oct 03 02:51:26 2011 -0700 @@ -1012,6 +1012,8 @@ if (STARTS_WITH(CLASSNAME(op), "Xen")) def_weight = DEFAULT_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(op), "QEMU")) + def_weight = DEFAULT_KVM_WEIGHT; rc = cu_get_u64_prop(inst, "Limit", &dev->dev.vcpu.limit); if (rc != CMPI_RC_OK) diff -r fb09136deb49 -r 2c9a378e141c src/Virt_VirtualSystemManagementService.h --- a/src/Virt_VirtualSystemManagementService.h Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_VirtualSystemManagementService.h Mon Oct 03 02:51:26 2011 -0700 @@ -24,6 +24,11 @@ #define INC_XEN_WEIGHT MAX_XEN_WEIGHT / 2 #define DEFAULT_XEN_WEIGHT 1024 +#define MIN_KVM_WEIGHT 2 +#define MAX_KVM_WEIGHT 262144 +#define INC_KVM_WEIGHT 1 +#define DEFAULT_KVM_WEIGHT 1024 + CMPIStatus get_vsms(const CMPIObjectPath *reference, CMPIInstance **_inst, const CMPIBroker *broker,

Tested on my laptop with libvirt 0.9.4, this version have cgroup feature added for inactive guest, but the libvirt-cim also acts as expected. Tested-by: Wayne Xia <xiawenc@linux.vnet.ibm.com> 于 2011-10-3 17:52, Gareth S. Bestor 写道:
# HG changeset patch # User Gareth S. Bestor<bestor@us.ibm.com> # Date 1317635486 25200 # Node ID 2c9a378e141c23eae0b96b2f021adbd14cfb8ef2 # Parent fb09136deb494008eb3aacee420ad74da7d7c294 Add support for libvirt CPU cgroup for active KVM guests Add support for setting and retreiving the CPU cgroup setting for an active KVM guest using libivirt scheduling parameter support. Presently this patches only supports earlier libvirt versions' support of this feature, which only support setting these scheduling params for *active* guests only, and uses libivrt's earlier scheduling APIs; a subsequent patch will support both and the newer APIs (version dependent). A guest's CPU cgroup setting it exposed via the KVM_ProcResourceAllocationSettingData.Weight property. Minimum, maximum, Increment and Default weights are exposed appropriately via the respective Processor pool. Weight for new guest can be passed in on DefineSystem[] Weigh for existing (active) guest can be changed via ModifyResourceSettings[] Signed-off-by: Gareth S. Bestor<bestor@us.bm.com>
diff -r fb09136deb49 -r 2c9a378e141c libxkutil/device_parsing.c --- a/libxkutil/device_parsing.c Tue Aug 30 08:48:36 2011 -0700 +++ b/libxkutil/device_parsing.c Mon Oct 03 02:51:26 2011 -0700 @@ -1297,6 +1297,24 @@ { int ret;
+ /* Change vcpu cgroup cpu_shares */ + if (dev->dev.vcpu.weight> 0) { + virSchedParameter param; + + strncpy(param.field, "cpu_shares", VIR_DOMAIN_SCHED_FIELD_LENGTH); + param.type = VIR_DOMAIN_SCHED_FIELD_ULLONG; + param.value.ul = dev->dev.vcpu.weight; + + if (virDomainSetSchedulerParameters(dom,¶m, 1) != 0) { + CU_DEBUG("Failed to set scheduler params for domain"); + return 0; + } + + CU_DEBUG("Changed %s vcpu cgroup cpu_shares to %i", + virDomainGetName(dom), + dev->dev.vcpu.weight); + } + if (dev->dev.vcpu.quantity<= 0) { CU_DEBUG("Unable to set VCPU count to %i", dev->dev.vcpu.quantity); diff -r fb09136deb49 -r 2c9a378e141c src/Virt_ComputerSystem.c --- a/src/Virt_ComputerSystem.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_ComputerSystem.c Mon Oct 03 02:51:26 2011 -0700 @@ -858,6 +858,30 @@ return 0; }
+static int kvm_scheduler_params(struct infostore_ctx *ctx, + virSchedParameter **params) +{ + unsigned long long value; + + *params = calloc(1, sizeof(virSchedParameter)); + if (*params == NULL) + return -1; + + value = infostore_get_u64(ctx, "weight"); + + if (value != 0) { + strncpy((*params)[0].field, + "cpu_shares", + VIR_DOMAIN_SCHED_FIELD_LENGTH); + (*params)[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG; + (*params)[0].value.ul = value; + + return 1; + } + + return 0; +} + static void set_scheduler_params(virDomainPtr dom) { struct infostore_ctx *ctx; @@ -881,6 +905,8 @@ count = xen_scheduler_params(ctx,¶ms); else if (STREQC(virConnectGetType(conn), "lxc")) count = lxc_scheduler_params(ctx,¶ms); + else if (STREQC(virConnectGetType(conn), "QEMU")) + count = kvm_scheduler_params(ctx,¶ms); else { CU_DEBUG("Not setting sched params for type %s", virConnectGetType(conn)); diff -r fb09136deb49 -r 2c9a378e141c src/Virt_RASD.c --- a/src/Virt_RASD.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_RASD.c Mon Oct 03 02:51:26 2011 -0700 @@ -110,7 +110,7 @@ virConnectPtr conn = NULL; virDomainPtr dom = NULL; struct infostore_ctx *info = NULL; - uint32_t weight; + uint32_t weight = 0; uint64_t limit; uint64_t count;
@@ -147,7 +147,45 @@ goto out; }
- weight = (uint32_t)infostore_get_u64(info, "weight"); + /* Currently only support CPU cgroups for running KVM guests */ + if (domain_online(dom)&& STREQC(virConnectGetType(conn), "QEMU")) { + char *sched; + int nparams; + unsigned int i; + virSchedParameter *params; + + /* First find the number of scheduler params, in order malloc space for them all */ + sched = virDomainGetSchedulerType(dom,&nparams); + if (sched == NULL) { + CU_DEBUG("Failed to get scheduler type"); + goto out; + } + CU_DEBUG("domain has %d scheduler params", nparams); + free(sched); + + /* Now retrieve all the scheduler params for this domain */ + params = calloc(nparams, sizeof(virSchedParameter)); + if (virDomainGetSchedulerParameters(dom, params,&nparams) != 0) { + CU_DEBUG("Failed to get scheduler params for domain"); + goto out; + } + + /* Look for the CPU cgroup scheduler parameter, called 'cpu_shares' */ + for (i = 0 ; i< nparams ; i++) { + CU_DEBUG("scheduler param #%d name is %s (type %d)", + i, params[i].field, params[i].type); + if (STREQ(params[i].field, "cpu_shares")&& + (params[i].type == VIR_DOMAIN_SCHED_FIELD_ULLONG)) { + CU_DEBUG("scheduler param %s = %d", + params[i].field, params[i].value.ul); + weight = (uint32_t)params[i].value.ul; + break; /* Found it! */ + } + } + free(params); + } + else + weight = (uint32_t)infostore_get_u64(info, "weight"); limit = infostore_get_u64(info, "limit");
CMSetProperty(inst, "Weight", diff -r fb09136deb49 -r 2c9a378e141c src/Virt_SettingsDefineCapabilities.c --- a/src/Virt_SettingsDefineCapabilities.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_SettingsDefineCapabilities.c Mon Oct 03 02:51:26 2011 -0700 @@ -410,7 +410,10 @@ case SDC_RASD_MIN: num_procs = 0; limit = 1; - weight = MIN_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = MIN_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = MIN_KVM_WEIGHT; id = "Minimum"; break; case SDC_RASD_MAX: @@ -418,19 +421,28 @@ if (!ret) goto out; limit = 0; - weight = MAX_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = MAX_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = MAX_KVM_WEIGHT; id = "Maximum"; break; case SDC_RASD_INC: num_procs = 1; limit = 50; - weight = INC_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = INC_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = INC_KVM_WEIGHT; id = "Increment"; break; case SDC_RASD_DEF: num_procs = 1; limit = 0; - weight = DEFAULT_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = DEFAULT_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = DEFAULT_KVM_WEIGHT; id = "Default"; break; default: @@ -455,6 +467,10 @@ CMSetProperty(inst, "Weight", (CMPIValue *)&weight, CMPI_uint32); } + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) { + CMSetProperty(inst, "Weight", + (CMPIValue *)&weight, CMPI_uint32); + }
inst_list_add(list, inst);
diff -r fb09136deb49 -r 2c9a378e141c src/Virt_VirtualSystemManagementService.c --- a/src/Virt_VirtualSystemManagementService.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_VirtualSystemManagementService.c Mon Oct 03 02:51:26 2011 -0700 @@ -1012,6 +1012,8 @@
if (STARTS_WITH(CLASSNAME(op), "Xen")) def_weight = DEFAULT_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(op), "QEMU")) + def_weight = DEFAULT_KVM_WEIGHT;
rc = cu_get_u64_prop(inst, "Limit",&dev->dev.vcpu.limit); if (rc != CMPI_RC_OK) diff -r fb09136deb49 -r 2c9a378e141c src/Virt_VirtualSystemManagementService.h --- a/src/Virt_VirtualSystemManagementService.h Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_VirtualSystemManagementService.h Mon Oct 03 02:51:26 2011 -0700 @@ -24,6 +24,11 @@ #define INC_XEN_WEIGHT MAX_XEN_WEIGHT / 2 #define DEFAULT_XEN_WEIGHT 1024
+#define MIN_KVM_WEIGHT 2 +#define MAX_KVM_WEIGHT 262144 +#define INC_KVM_WEIGHT 1 +#define DEFAULT_KVM_WEIGHT 1024 + CMPIStatus get_vsms(const CMPIObjectPath *reference, CMPIInstance **_inst, const CMPIBroker *broker,
_______________________________________________ Libvirt-cim mailing list Libvirt-cim@redhat.com https://www.redhat.com/mailman/listinfo/libvirt-cim
-- Best Regards Wayne Xia mail:xiawenc@linux.vnet.ibm.com tel:86-010-82450803

Thanks. Pushed. On 10/13/2011 04:30 AM, Wayne Xia wrote:
Tested on my laptop with libvirt 0.9.4, this version have cgroup feature added for inactive guest, but the libvirt-cim also acts as expected.
Tested-by: Wayne Xia <xiawenc@linux.vnet.ibm.com>
于 2011-10-3 17:52, Gareth S. Bestor 写道:
# HG changeset patch # User Gareth S. Bestor<bestor@us.ibm.com> # Date 1317635486 25200 # Node ID 2c9a378e141c23eae0b96b2f021adbd14cfb8ef2 # Parent fb09136deb494008eb3aacee420ad74da7d7c294 Add support for libvirt CPU cgroup for active KVM guests Add support for setting and retreiving the CPU cgroup setting for an active KVM guest using libivirt scheduling parameter support. Presently this patches only supports earlier libvirt versions' support of this feature, which only support setting these scheduling params for *active* guests only, and uses libivrt's earlier scheduling APIs; a subsequent patch will support both and the newer APIs (version dependent). A guest's CPU cgroup setting it exposed via the KVM_ProcResourceAllocationSettingData.Weight property. Minimum, maximum, Increment and Default weights are exposed appropriately via the respective Processor pool. Weight for new guest can be passed in on DefineSystem[] Weigh for existing (active) guest can be changed via ModifyResourceSettings[] Signed-off-by: Gareth S. Bestor<bestor@us.bm.com>
diff -r fb09136deb49 -r 2c9a378e141c libxkutil/device_parsing.c --- a/libxkutil/device_parsing.c Tue Aug 30 08:48:36 2011 -0700 +++ b/libxkutil/device_parsing.c Mon Oct 03 02:51:26 2011 -0700 @@ -1297,6 +1297,24 @@ { int ret;
+ /* Change vcpu cgroup cpu_shares */ + if (dev->dev.vcpu.weight> 0) { + virSchedParameter param; + + strncpy(param.field, "cpu_shares", VIR_DOMAIN_SCHED_FIELD_LENGTH); + param.type = VIR_DOMAIN_SCHED_FIELD_ULLONG; + param.value.ul = dev->dev.vcpu.weight; + + if (virDomainSetSchedulerParameters(dom,¶m, 1) != 0) { + CU_DEBUG("Failed to set scheduler params for domain"); + return 0; + } + + CU_DEBUG("Changed %s vcpu cgroup cpu_shares to %i", + virDomainGetName(dom), + dev->dev.vcpu.weight); + } + if (dev->dev.vcpu.quantity<= 0) { CU_DEBUG("Unable to set VCPU count to %i", dev->dev.vcpu.quantity); diff -r fb09136deb49 -r 2c9a378e141c src/Virt_ComputerSystem.c --- a/src/Virt_ComputerSystem.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_ComputerSystem.c Mon Oct 03 02:51:26 2011 -0700 @@ -858,6 +858,30 @@ return 0; }
+static int kvm_scheduler_params(struct infostore_ctx *ctx, + virSchedParameter **params) +{ + unsigned long long value; + + *params = calloc(1, sizeof(virSchedParameter)); + if (*params == NULL) + return -1; + + value = infostore_get_u64(ctx, "weight"); + + if (value != 0) { + strncpy((*params)[0].field, + "cpu_shares", + VIR_DOMAIN_SCHED_FIELD_LENGTH); + (*params)[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG; + (*params)[0].value.ul = value; + + return 1; + } + + return 0; +} + static void set_scheduler_params(virDomainPtr dom) { struct infostore_ctx *ctx; @@ -881,6 +905,8 @@ count = xen_scheduler_params(ctx,¶ms); else if (STREQC(virConnectGetType(conn), "lxc")) count = lxc_scheduler_params(ctx,¶ms); + else if (STREQC(virConnectGetType(conn), "QEMU")) + count = kvm_scheduler_params(ctx,¶ms); else { CU_DEBUG("Not setting sched params for type %s", virConnectGetType(conn)); diff -r fb09136deb49 -r 2c9a378e141c src/Virt_RASD.c --- a/src/Virt_RASD.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_RASD.c Mon Oct 03 02:51:26 2011 -0700 @@ -110,7 +110,7 @@ virConnectPtr conn = NULL; virDomainPtr dom = NULL; struct infostore_ctx *info = NULL; - uint32_t weight; + uint32_t weight = 0; uint64_t limit; uint64_t count;
@@ -147,7 +147,45 @@ goto out; }
- weight = (uint32_t)infostore_get_u64(info, "weight"); + /* Currently only support CPU cgroups for running KVM guests */ + if (domain_online(dom)&& STREQC(virConnectGetType(conn), "QEMU")) { + char *sched; + int nparams; + unsigned int i; + virSchedParameter *params; + + /* First find the number of scheduler params, in order malloc space for them all */ + sched = virDomainGetSchedulerType(dom,&nparams); + if (sched == NULL) { + CU_DEBUG("Failed to get scheduler type"); + goto out; + } + CU_DEBUG("domain has %d scheduler params", nparams); + free(sched); + + /* Now retrieve all the scheduler params for this domain */ + params = calloc(nparams, sizeof(virSchedParameter)); + if (virDomainGetSchedulerParameters(dom, params,&nparams) != 0) { + CU_DEBUG("Failed to get scheduler params for domain"); + goto out; + } + + /* Look for the CPU cgroup scheduler parameter, called 'cpu_shares' */ + for (i = 0 ; i< nparams ; i++) { + CU_DEBUG("scheduler param #%d name is %s (type %d)", + i, params[i].field, params[i].type); + if (STREQ(params[i].field, "cpu_shares")&& + (params[i].type == VIR_DOMAIN_SCHED_FIELD_ULLONG)) { + CU_DEBUG("scheduler param %s = %d", + params[i].field, params[i].value.ul); + weight = (uint32_t)params[i].value.ul; + break; /* Found it! */ + } + } + free(params); + } + else + weight = (uint32_t)infostore_get_u64(info, "weight"); limit = infostore_get_u64(info, "limit");
CMSetProperty(inst, "Weight", diff -r fb09136deb49 -r 2c9a378e141c src/Virt_SettingsDefineCapabilities.c --- a/src/Virt_SettingsDefineCapabilities.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_SettingsDefineCapabilities.c Mon Oct 03 02:51:26 2011 -0700 @@ -410,7 +410,10 @@ case SDC_RASD_MIN: num_procs = 0; limit = 1; - weight = MIN_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = MIN_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = MIN_KVM_WEIGHT; id = "Minimum"; break; case SDC_RASD_MAX: @@ -418,19 +421,28 @@ if (!ret) goto out; limit = 0; - weight = MAX_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = MAX_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = MAX_KVM_WEIGHT; id = "Maximum"; break; case SDC_RASD_INC: num_procs = 1; limit = 50; - weight = INC_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = INC_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = INC_KVM_WEIGHT; id = "Increment"; break; case SDC_RASD_DEF: num_procs = 1; limit = 0; - weight = DEFAULT_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = DEFAULT_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = DEFAULT_KVM_WEIGHT; id = "Default"; break; default: @@ -455,6 +467,10 @@ CMSetProperty(inst, "Weight", (CMPIValue *)&weight, CMPI_uint32); } + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) { + CMSetProperty(inst, "Weight", + (CMPIValue *)&weight, CMPI_uint32); + }
inst_list_add(list, inst);
diff -r fb09136deb49 -r 2c9a378e141c src/Virt_VirtualSystemManagementService.c --- a/src/Virt_VirtualSystemManagementService.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_VirtualSystemManagementService.c Mon Oct 03 02:51:26 2011 -0700 @@ -1012,6 +1012,8 @@
if (STARTS_WITH(CLASSNAME(op), "Xen")) def_weight = DEFAULT_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(op), "QEMU")) + def_weight = DEFAULT_KVM_WEIGHT;
rc = cu_get_u64_prop(inst, "Limit",&dev->dev.vcpu.limit); if (rc != CMPI_RC_OK) diff -r fb09136deb49 -r 2c9a378e141c src/Virt_VirtualSystemManagementService.h --- a/src/Virt_VirtualSystemManagementService.h Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_VirtualSystemManagementService.h Mon Oct 03 02:51:26 2011 -0700 @@ -24,6 +24,11 @@ #define INC_XEN_WEIGHT MAX_XEN_WEIGHT / 2 #define DEFAULT_XEN_WEIGHT 1024
+#define MIN_KVM_WEIGHT 2 +#define MAX_KVM_WEIGHT 262144 +#define INC_KVM_WEIGHT 1 +#define DEFAULT_KVM_WEIGHT 1024 + CMPIStatus get_vsms(const CMPIObjectPath *reference, CMPIInstance **_inst, const CMPIBroker *broker,
_______________________________________________ Libvirt-cim mailing list Libvirt-cim@redhat.com https://www.redhat.com/mailman/listinfo/libvirt-cim
-- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent@linux.vnet.ibm.com

Default: wbemcli -nl -arc KVM_ProcResourceAllocationSettingData ai 'local/root/virt:KVM_Processor.CreationClassName="KVM_Processor",DeviceID="WinXP10/0",SystemCreationClassName="KVM_ComputerSystem",SystemName="WinXP10"' oc0840652111.ibm.com/root /virt:KVM_ProcResourceAllocationSettingData.InstanceID="WinXP10/proc" -Caption= -Description= -Generation= -InstanceID="WinXP10/proc" -ElementName= -ConfigurationName= -ChangeableType= -ResourceType=3 -OtherResourceType= -ResourceSubType= -PoolID= -ConsumerVisibility= -HostResource= -AllocationUnits= -VirtualQuantity=1 -Reservation= -Limit=0 -Weight=1024 -AutomaticAllocation= -AutomaticDeallocation= -Parent= -Connection= -Address= -MappingBehavior= -AddressOnParent= -VirtualQuantityUnits="count" Change CPU share outside of CIM: # virsh schedinfo --set cpu_shares=512 WinXP10 Scheduler : posix cpu_shares : 512 # wbemcli -nl -arc KVM_ProcResourceAllocationSettingData ai 'local/root/virt:KVM_Processor.CreationClassName="KVM_Processor",DeviceID="WinXP10/0",SystemCreationClassName="KVM_ComputerSystem",SystemName="WinXP10"' oc0840652111.ibm.com/root/virt:KVM_ProcResourceAllocationSettingData.InstanceID="WinXP10/proc" -Caption= -Description= -Generation= -InstanceID="WinXP10/proc" -ElementName= -ConfigurationName= -ChangeableType= -ResourceType=3 -OtherResourceType= -ResourceSubType= -PoolID= -ConsumerVisibility= -HostResource= -AllocationUnits= -VirtualQuantity=1 -Reservation= -Limit=0 -Weight=512 -AutomaticAllocation= -AutomaticDeallocation= -Parent= -Connection= -Address= -MappingBehavior= -AddressOnParent= -VirtualQuantityUnits="count" I'm getting the following error when I try to modify via CIM. HTTP/1.1 401 Unauthorized content-length: 0000000000 WWW-Authenticate: Basic realm="oc0840652111.ibm.com" But I think that is a problem with my configuration, not the patch. +1. Thanks, Gareth. On 10/03/2011 05:52 AM, Gareth S. Bestor wrote:
# HG changeset patch # User Gareth S. Bestor<bestor@us.ibm.com> # Date 1317635486 25200 # Node ID 2c9a378e141c23eae0b96b2f021adbd14cfb8ef2 # Parent fb09136deb494008eb3aacee420ad74da7d7c294 Add support for libvirt CPU cgroup for active KVM guests Add support for setting and retreiving the CPU cgroup setting for an active KVM guest using libivirt scheduling parameter support. Presently this patches only supports earlier libvirt versions' support of this feature, which only support setting these scheduling params for *active* guests only, and uses libivrt's earlier scheduling APIs; a subsequent patch will support both and the newer APIs (version dependent). A guest's CPU cgroup setting it exposed via the KVM_ProcResourceAllocationSettingData.Weight property. Minimum, maximum, Increment and Default weights are exposed appropriately via the respective Processor pool. Weight for new guest can be passed in on DefineSystem[] Weigh for existing (active) guest can be changed via ModifyResourceSettings[] Signed-off-by: Gareth S. Bestor<bestor@us.bm.com>
diff -r fb09136deb49 -r 2c9a378e141c libxkutil/device_parsing.c --- a/libxkutil/device_parsing.c Tue Aug 30 08:48:36 2011 -0700 +++ b/libxkutil/device_parsing.c Mon Oct 03 02:51:26 2011 -0700 @@ -1297,6 +1297,24 @@ { int ret;
+ /* Change vcpu cgroup cpu_shares */ + if (dev->dev.vcpu.weight> 0) { + virSchedParameter param; + + strncpy(param.field, "cpu_shares", VIR_DOMAIN_SCHED_FIELD_LENGTH); + param.type = VIR_DOMAIN_SCHED_FIELD_ULLONG; + param.value.ul = dev->dev.vcpu.weight; + + if (virDomainSetSchedulerParameters(dom,¶m, 1) != 0) { + CU_DEBUG("Failed to set scheduler params for domain"); + return 0; + } + + CU_DEBUG("Changed %s vcpu cgroup cpu_shares to %i", + virDomainGetName(dom), + dev->dev.vcpu.weight); + } + if (dev->dev.vcpu.quantity<= 0) { CU_DEBUG("Unable to set VCPU count to %i", dev->dev.vcpu.quantity); diff -r fb09136deb49 -r 2c9a378e141c src/Virt_ComputerSystem.c --- a/src/Virt_ComputerSystem.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_ComputerSystem.c Mon Oct 03 02:51:26 2011 -0700 @@ -858,6 +858,30 @@ return 0; }
+static int kvm_scheduler_params(struct infostore_ctx *ctx, + virSchedParameter **params) +{ + unsigned long long value; + + *params = calloc(1, sizeof(virSchedParameter)); + if (*params == NULL) + return -1; + + value = infostore_get_u64(ctx, "weight"); + + if (value != 0) { + strncpy((*params)[0].field, + "cpu_shares", + VIR_DOMAIN_SCHED_FIELD_LENGTH); + (*params)[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG; + (*params)[0].value.ul = value; + + return 1; + } + + return 0; +} + static void set_scheduler_params(virDomainPtr dom) { struct infostore_ctx *ctx; @@ -881,6 +905,8 @@ count = xen_scheduler_params(ctx,¶ms); else if (STREQC(virConnectGetType(conn), "lxc")) count = lxc_scheduler_params(ctx,¶ms); + else if (STREQC(virConnectGetType(conn), "QEMU")) + count = kvm_scheduler_params(ctx,¶ms); else { CU_DEBUG("Not setting sched params for type %s", virConnectGetType(conn)); diff -r fb09136deb49 -r 2c9a378e141c src/Virt_RASD.c --- a/src/Virt_RASD.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_RASD.c Mon Oct 03 02:51:26 2011 -0700 @@ -110,7 +110,7 @@ virConnectPtr conn = NULL; virDomainPtr dom = NULL; struct infostore_ctx *info = NULL; - uint32_t weight; + uint32_t weight = 0; uint64_t limit; uint64_t count;
@@ -147,7 +147,45 @@ goto out; }
- weight = (uint32_t)infostore_get_u64(info, "weight"); + /* Currently only support CPU cgroups for running KVM guests */ + if (domain_online(dom)&& STREQC(virConnectGetType(conn), "QEMU")) { + char *sched; + int nparams; + unsigned int i; + virSchedParameter *params; + + /* First find the number of scheduler params, in order malloc space for them all */ + sched = virDomainGetSchedulerType(dom,&nparams); + if (sched == NULL) { + CU_DEBUG("Failed to get scheduler type"); + goto out; + } + CU_DEBUG("domain has %d scheduler params", nparams); + free(sched); + + /* Now retrieve all the scheduler params for this domain */ + params = calloc(nparams, sizeof(virSchedParameter)); + if (virDomainGetSchedulerParameters(dom, params,&nparams) != 0) { + CU_DEBUG("Failed to get scheduler params for domain"); + goto out; + } + + /* Look for the CPU cgroup scheduler parameter, called 'cpu_shares' */ + for (i = 0 ; i< nparams ; i++) { + CU_DEBUG("scheduler param #%d name is %s (type %d)", + i, params[i].field, params[i].type); + if (STREQ(params[i].field, "cpu_shares")&& + (params[i].type == VIR_DOMAIN_SCHED_FIELD_ULLONG)) { + CU_DEBUG("scheduler param %s = %d", + params[i].field, params[i].value.ul); + weight = (uint32_t)params[i].value.ul; + break; /* Found it! */ + } + } + free(params); + } + else + weight = (uint32_t)infostore_get_u64(info, "weight"); limit = infostore_get_u64(info, "limit");
CMSetProperty(inst, "Weight", diff -r fb09136deb49 -r 2c9a378e141c src/Virt_SettingsDefineCapabilities.c --- a/src/Virt_SettingsDefineCapabilities.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_SettingsDefineCapabilities.c Mon Oct 03 02:51:26 2011 -0700 @@ -410,7 +410,10 @@ case SDC_RASD_MIN: num_procs = 0; limit = 1; - weight = MIN_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = MIN_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = MIN_KVM_WEIGHT; id = "Minimum"; break; case SDC_RASD_MAX: @@ -418,19 +421,28 @@ if (!ret) goto out; limit = 0; - weight = MAX_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = MAX_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = MAX_KVM_WEIGHT; id = "Maximum"; break; case SDC_RASD_INC: num_procs = 1; limit = 50; - weight = INC_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = INC_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = INC_KVM_WEIGHT; id = "Increment"; break; case SDC_RASD_DEF: num_procs = 1; limit = 0; - weight = DEFAULT_XEN_WEIGHT; + if (STARTS_WITH(CLASSNAME(ref), "Xen")) + weight = DEFAULT_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) + weight = DEFAULT_KVM_WEIGHT; id = "Default"; break; default: @@ -455,6 +467,10 @@ CMSetProperty(inst, "Weight", (CMPIValue *)&weight, CMPI_uint32); } + else if (STARTS_WITH(CLASSNAME(ref), "KVM")) { + CMSetProperty(inst, "Weight", + (CMPIValue *)&weight, CMPI_uint32); + }
inst_list_add(list, inst);
diff -r fb09136deb49 -r 2c9a378e141c src/Virt_VirtualSystemManagementService.c --- a/src/Virt_VirtualSystemManagementService.c Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_VirtualSystemManagementService.c Mon Oct 03 02:51:26 2011 -0700 @@ -1012,6 +1012,8 @@
if (STARTS_WITH(CLASSNAME(op), "Xen")) def_weight = DEFAULT_XEN_WEIGHT; + else if (STARTS_WITH(CLASSNAME(op), "QEMU")) + def_weight = DEFAULT_KVM_WEIGHT;
rc = cu_get_u64_prop(inst, "Limit",&dev->dev.vcpu.limit); if (rc != CMPI_RC_OK) diff -r fb09136deb49 -r 2c9a378e141c src/Virt_VirtualSystemManagementService.h --- a/src/Virt_VirtualSystemManagementService.h Tue Aug 30 08:48:36 2011 -0700 +++ b/src/Virt_VirtualSystemManagementService.h Mon Oct 03 02:51:26 2011 -0700 @@ -24,6 +24,11 @@ #define INC_XEN_WEIGHT MAX_XEN_WEIGHT / 2 #define DEFAULT_XEN_WEIGHT 1024
+#define MIN_KVM_WEIGHT 2 +#define MAX_KVM_WEIGHT 262144 +#define INC_KVM_WEIGHT 1 +#define DEFAULT_KVM_WEIGHT 1024 + CMPIStatus get_vsms(const CMPIObjectPath *reference, CMPIInstance **_inst, const CMPIBroker *broker,
_______________________________________________ Libvirt-cim mailing list Libvirt-cim@redhat.com https://www.redhat.com/mailman/listinfo/libvirt-cim
-- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent@linux.vnet.ibm.com
participants (3)
-
Chip Vincent
-
Gareth S. Bestor
-
Wayne Xia