Implement the following:
- virDomainGetSchedulerType
- virDomainSetSchedulerParameters
- virDomainSetSchedulerParametersFlags
- virDomainGetSchedulerParameters
- virDomainGetSchedulerParametersFlags
Signed-off-by: Vineeth Remanan Pillai <vpilllai(a)digitalocean.com>
---
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