Implement the following: - virDomainGetSchedulerType - virDomainSetSchedulerParameters - virDomainSetSchedulerParametersFlags - virDomainGetSchedulerParameters - virDomainGetSchedulerParametersFlags Signed-off-by: Vineeth Remanan Pillai <vpilllai@xxxxxxxxxxxxxxxx> --- examples/hello.rs | 38 +++++++ src/domain.rs | 260 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 283 insertions(+), 15 deletions(-) diff --git a/examples/hello.rs b/examples/hello.rs index e5ec6e4..1f336a9 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -89,6 +89,44 @@ fn show_domains(conn: &Connect) -> Result<(), Error> { numa.node_set.unwrap_or(String::from(""))); println!(" Mode: {}", numa.mode.unwrap_or(0)); } + + if let Ok((sched_type, nparams)) = dom.get_scheduler_type() { + println!("SchedType: {}, nparams: {}", + sched_type, nparams); + } + + if let Ok(sched_info) = dom.get_scheduler_parameters() { + println!("Schedule Information:"); + println!("\tScheduler\t: {}", sched_info.scheduler_type); + if let Some(shares) = sched_info.cpu_shares { + println!("\tcpu_shares\t: {}", shares); + } + if let Some(period) = sched_info.vcpu_bw.period { + println!("\tvcpu_period\t: {}", period); + } + if let Some(quota) = sched_info.vcpu_bw.quota { + println!("\tvcpu_quota\t: {}", quota); + } + if let Some(period) = sched_info.emulator_bw.period { + println!("\temulator_period\t: {}", period); + } + if let Some(quota) = sched_info.emulator_bw.quota { + println!("\temulator_quota\t: {}", quota); + } + if let Some(period) = sched_info.global_bw.period { + println!("\tglobal_period\t: {}", period); + } + if let Some(quota) = sched_info.global_bw.quota { + println!("\tglobal_quota\t: {}", quota); + } + if let Some(period) = sched_info.global_bw.period { + println!("\tiothread_period\t: {}", period); + } + if let Some(quota) = sched_info.global_bw.quota { + println!("\tiothread_quota\t: {}", quota); + } + } + } } return Ok(()); diff --git a/src/domain.rs b/src/domain.rs index acb9e6e..40a18d8 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -363,6 +363,29 @@ extern "C" { snaps: *mut *mut virDomainSnapshotPtr, flags: libc::c_uint) -> libc::c_int; + + fn virDomainGetSchedulerType(ptr: sys::virDomainPtr, + nparams: *mut libc::c_int) + -> *mut libc::c_char; + fn virDomainGetSchedulerParameters(ptr: sys::virDomainPtr, + params: virTypedParameterPtr, + nparams: *mut libc::c_int) + -> libc::c_int; + fn virDomainSetSchedulerParameters(ptr: sys::virDomainPtr, + params: virTypedParameterPtr, + nparams: libc::c_int) + -> libc::c_int; + fn virDomainGetSchedulerParametersFlags(ptr: sys::virDomainPtr, + params: virTypedParameterPtr, + nparams: *mut libc::c_int, + flags: libc::c_uint) + -> libc::c_int; + fn virDomainSetSchedulerParametersFlags(ptr: sys::virDomainPtr, + params: virTypedParameterPtr, + nparams: libc::c_int, + flags: libc::c_uint) + -> libc::c_int; + } pub type DomainXMLFlags = self::libc::c_uint; @@ -607,6 +630,124 @@ impl MemoryStats { } } +/// Structure representing the CFS scheduler cpu bandwidth parameters +/// see https://www.kernel.org/doc/html/latest/scheduler/sched-bwc.html +#[derive(Clone, Debug, Default)] +pub struct SchedBandwidth { + pub period: Option<u64>, + pub quota: Option<i64>, +} + +#[derive(Clone, Debug, Default)] +pub struct SchedulerInfo { + pub scheduler_type: String, + // cpu shares for the domain. + pub cpu_shares: Option<u64>, + // Bandwidth allocated for the vcpu threads. + pub vcpu_bw: SchedBandwidth, + // Bandwidth allocated for the emulator threads. + pub emulator_bw: SchedBandwidth, + // Bandwidth allocated for the Domain. + pub global_bw: SchedBandwidth, + // Bandwidth allocated for the io threads.. + pub iothread_bw: SchedBandwidth, +} + +impl SchedulerInfo { + pub fn from_vec(vec: Vec<virTypedParameter>, scheduler_type: String) -> SchedulerInfo { + unsafe { + let mut ret = SchedulerInfo::default(); + ret.scheduler_type = scheduler_type; + for param in vec { + match str::from_utf8(CStr::from_ptr(param.field.as_ptr()).to_bytes()).unwrap() { + "cpu_shares" => ret.cpu_shares = Some(param.value as u64), + "vcpu_period" => ret.vcpu_bw.period = Some(param.value as u64), + "vcpu_quota" => ret.vcpu_bw.quota = Some(param.value as i64), + "emulator_period" => ret.emulator_bw.period = Some(param.value as u64), + "emulator_quota" => ret.emulator_bw.quota = Some(param.value as i64), + "global_period" => ret.global_bw.period = Some(param.value as u64), + "global_quota" => ret.global_bw.quota = Some(param.value as i64), + "iothread_period" => ret.iothread_bw.period = Some(param.value as u64), + "iothread_quota" => ret.iothread_bw.quota = Some(param.value as i64), + unknow => panic!("Field not implemented for SchedulerInfo, {:?}", unknow), + } + } + ret + } + } + + pub fn to_vec(&self) -> Vec<virTypedParameter> { + let mut cparams: Vec<virTypedParameter> = Vec::new(); + + if let Some(shares) = self.cpu_shares { + cparams.push(virTypedParameter { + field: to_arr("cpu_shares\0"), + typed: ::typedparam::VIR_TYPED_PARAM_ULLONG, + value: shares + }); + } + + if let Some(period) = self.vcpu_bw.period { + cparams.push(virTypedParameter { + field: to_arr("vcpu_period\0"), + typed: ::typedparam::VIR_TYPED_PARAM_ULLONG, + value: period, + }); + } + if let Some(quota) = self.vcpu_bw.quota { + cparams.push(virTypedParameter { + field: to_arr("vcpu_quota\0"), + typed: ::typedparam::VIR_TYPED_PARAM_LLONG, + value: quota as u64, + }); + } + if let Some(period) = self.emulator_bw.period { + cparams.push(virTypedParameter { + field: to_arr("emulator_period\0"), + typed: ::typedparam::VIR_TYPED_PARAM_ULLONG, + value: period, + }); + } + if let Some(quota) = self.emulator_bw.quota { + cparams.push(virTypedParameter { + field: to_arr("emulator_quota\0"), + typed: ::typedparam::VIR_TYPED_PARAM_LLONG, + value: quota as u64, + }); + } + if let Some(period) = self.global_bw.period { + cparams.push(virTypedParameter { + field: to_arr("global_period\0"), + typed: ::typedparam::VIR_TYPED_PARAM_ULLONG, + value: period, + }); + } + if let Some(quota) = self.global_bw.quota { + cparams.push(virTypedParameter { + field: to_arr("global_quota\0"), + typed: ::typedparam::VIR_TYPED_PARAM_LLONG, + value: quota as u64, + }); + } + if let Some(period) = self.iothread_bw.period { + cparams.push(virTypedParameter { + field: to_arr("iothread_period\0"), + typed: ::typedparam::VIR_TYPED_PARAM_ULLONG, + value: period, + }); + } + if let Some(quota) = self.iothread_bw.quota { + cparams.push(virTypedParameter { + field: to_arr("iothread_quota\0"), + typed: ::typedparam::VIR_TYPED_PARAM_LLONG, + value: quota as u64, + }); + } + + cparams + } +} + /// Provides APIs for the management of domains. /// /// See http://libvirt.org/html/libvirt-libvirt-domain.html @@ -627,6 +768,14 @@ impl Drop for Domain { } } +fn to_arr(name: &str) -> [libc::c_char; 80] { + let mut field: [libc::c_char; 80] = [0; 80]; + for (a, c) in field.iter_mut().zip(name.as_bytes()) { + *a = *c as i8 + } + field +} + impl Domain { pub fn new(ptr: sys::virDomainPtr) -> Domain { return Domain { ptr: Some(ptr) }; @@ -1656,14 +1805,6 @@ impl Domain { flags: u32) -> Result<u32, Error> { unsafe { - fn to_arr(name: &str) -> [libc::c_char; 80] { - let mut field: [libc::c_char; 80] = [0; 80]; - for (a, c) in field.iter_mut().zip(name.as_bytes()) { - *a = *c as i8 - } - field - } - let mut cparams: Vec<virTypedParameter> = Vec::new(); if params.hard_limit.is_some() { cparams.push(virTypedParameter { @@ -1809,13 +1950,6 @@ impl Domain { pub fn set_numa_parameters(&self, params: NUMAParameters, flags: u32) -> Result<u32, Error> { unsafe { - fn to_arr(name: &str) -> [libc::c_char; 80] { - let mut field: [libc::c_char; 80] = [0; 80]; - for (a, c) in field.iter_mut().zip(name.as_bytes()) { - *a = *c as i8 - } - field - } let mut cparams: Vec<virTypedParameter> = Vec::new(); if params.node_set.is_some() { @@ -1863,4 +1997,100 @@ impl Domain { return Ok(array); } } + + /// Get the cpu scheduler type for the domain + pub fn get_scheduler_type(&self) -> Result<(String, i32), Error> + { + unsafe { + let mut nparams: libc::c_int = -1; + let sched_type = virDomainGetSchedulerType(self.as_ptr(), + &mut nparams); + if sched_type.is_null() { + return Err(Error::new()); + } + + return Ok((c_chars_to_string!(sched_type), nparams)); + } + } + + /// Get the scheduler parameters for the domain. + pub fn get_scheduler_parameters(&self) -> Result<SchedulerInfo, Error> { + + let (sched_type, mut nparams) = self.get_scheduler_type()?; + unsafe { + let mut params: Vec<virTypedParameter> = vec![ + virTypedParameter::default(); 9]; + let ret = virDomainGetSchedulerParameters(self.as_ptr(), + &mut params[0], + &mut nparams); + if ret == -1 { + return Err(Error::new()); + } + Ok(SchedulerInfo::from_vec(params, sched_type)) + } + + } + + /// Get the scheduler parameters for the domain for the configuration + /// as specified by the flags. + /// # Arguments + /// + /// * `flags` - Specifies the Domain Impact: CONFIG, LIVE or CURRENT. + pub fn get_scheduler_parameters_flags(&self, + flags: DomainModImpactFlags) + -> Result<SchedulerInfo, Error> { + + let (sched_type, mut nparams) = self.get_scheduler_type()?; + unsafe { + let mut params: Vec<virTypedParameter> = vec![ + virTypedParameter::default(); 9]; + let ret = virDomainGetSchedulerParametersFlags(self.as_ptr(), + &mut params[0], + &mut nparams, + flags as libc::c_uint); + if ret == -1 { + return Err(Error::new()); + } + Ok(SchedulerInfo::from_vec(params, sched_type)) + } + + } + + /// Set the scheduler parameters for the domain. + pub fn set_scheduler_parameters(&self, + sched_info: &SchedulerInfo) + -> Result<i32, Error> { + unsafe { + let mut params = sched_info.to_vec(); + let ret = virDomainSetSchedulerParameters(self.as_ptr(), + &mut params[0], + params.len() as libc::c_int); + if ret == -1 { + return Err(Error::new()); + } + Ok(ret) + } + } + + /// Set the scheduler parameters for the domain for the configuration + /// as specified by the flags. + /// # Arguments + /// + /// * `flags` - Specifies the Domain Impact: CONFIG, LIVE or CURRENT. + pub fn set_scheduler_parameters_flags(&self, + sched_info: &SchedulerInfo, + flags: DomainModImpactFlags) + -> Result<i32, Error> { + unsafe { + let mut params = sched_info.to_vec(); + let ret = virDomainSetSchedulerParametersFlags(self.as_ptr(), + &mut params[0], + params.len() as libc::c_int, + flags as libc::c_uint); + if ret == -1 { + return Err(Error::new()); + } + Ok(ret) + } + } } -- 2.17.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list