use std::ffi::CString;
use std::{mem, ptr, str};
use uuid::Uuid;
use crate::connect::Connect;
use crate::domain_snapshot::DomainSnapshot;
use crate::error::Error;
use crate::stream::Stream;
use crate::typedparams::{from_params, to_params};
use crate::util::c_ulong_to_u64;
use crate::{param_field_in, param_field_out};
#[derive(Clone, Debug)]
pub struct DomainInfo {
pub state: sys::virDomainState,
pub max_mem: u64,
pub memory: u64,
pub nr_virt_cpu: u32,
pub cpu_time: u64,
}
impl DomainInfo {
pub unsafe fn from_ptr(ptr: sys::virDomainInfoPtr) -> DomainInfo {
DomainInfo {
state: (*ptr).state as sys::virDomainState,
max_mem: c_ulong_to_u64((*ptr).maxMem),
memory: c_ulong_to_u64((*ptr).memory),
nr_virt_cpu: (*ptr).nrVirtCpu as u32,
cpu_time: (*ptr).cpuTime,
}
}
}
#[derive(Clone, Debug)]
pub struct BlockStats {
pub rd_req: i64,
pub rd_bytes: i64,
pub wr_req: i64,
pub wr_bytes: i64,
pub errs: i64,
}
impl BlockStats {
pub unsafe fn from_ptr(ptr: sys::virDomainBlockStatsPtr) -> BlockStats {
BlockStats {
rd_req: (*ptr).rd_req,
rd_bytes: (*ptr).rd_bytes,
wr_req: (*ptr).wr_req,
wr_bytes: (*ptr).wr_bytes,
errs: (*ptr).errs,
}
}
}
pub struct DomainStatsRecord {
pub ptr: sys::virDomainStatsRecordPtr,
}
#[derive(Clone, Debug)]
pub struct BlockInfo {
pub capacity: u64,
pub allocation: u64,
pub physical: u64,
}
impl BlockInfo {
pub unsafe fn from_ptr(ptr: sys::virDomainBlockInfoPtr) -> BlockInfo {
BlockInfo {
capacity: (*ptr).capacity,
allocation: (*ptr).allocation,
physical: (*ptr).physical,
}
}
}
#[derive(Clone, Debug, Default)]
pub struct MemoryParameters {
pub hard_limit: Option<u64>,
pub soft_limit: Option<u64>,
pub min_guarantee: Option<u64>,
pub swap_hard_limit: Option<u64>,
}
macro_rules! memory_parameters_fields {
($dir:ident, $var:ident) => {
vec![
$dir!(sys::VIR_DOMAIN_MEMORY_HARD_LIMIT, UInt64, $var.hard_limit),
$dir!(sys::VIR_DOMAIN_MEMORY_SOFT_LIMIT, UInt64, $var.soft_limit),
$dir!(
sys::VIR_DOMAIN_MEMORY_MIN_GUARANTEE,
UInt64,
$var.min_guarantee
),
$dir!(
sys::VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
UInt64,
$var.swap_hard_limit
),
]
};
}
impl MemoryParameters {
pub const VALUE_UNLIMITED: u64 = sys::VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
pub fn from_vec(vec: Vec<sys::virTypedParameter>) -> MemoryParameters {
let mut ret = MemoryParameters::default();
let fields = memory_parameters_fields!(param_field_in, ret);
from_params(vec, fields);
ret
}
pub fn to_vec(&self) -> Vec<sys::virTypedParameter> {
let fields = memory_parameters_fields!(param_field_out, self);
to_params(fields)
}
}
macro_rules! numa_parameters_fields {
($dir:ident, $var:ident) => {
vec![
$dir!(sys::VIR_DOMAIN_NUMA_NODESET, String, $var.node_set),
$dir!(sys::VIR_DOMAIN_NUMA_MODE, Int32, $var.mode),
]
};
}
#[derive(Clone, Debug, Default)]
pub struct NUMAParameters {
pub node_set: Option<String>,
pub mode: Option<i32>,
}
impl NUMAParameters {
pub fn from_vec(vec: Vec<sys::virTypedParameter>) -> NUMAParameters {
let mut ret = NUMAParameters::default();
let fields = numa_parameters_fields!(param_field_in, ret);
from_params(vec, fields);
ret
}
pub fn to_vec(&self) -> Vec<sys::virTypedParameter> {
let fields = numa_parameters_fields!(param_field_out, self);
to_params(fields)
}
}
macro_rules! migrate_parameters_fields {
($dir:ident, $var:ident) => {
vec![
$dir!(
sys::VIR_MIGRATE_PARAM_AUTO_CONVERGE_INCREMENT,
Int32,
$var.auto_converge_increment
),
$dir!(
sys::VIR_MIGRATE_PARAM_AUTO_CONVERGE_INITIAL,
Int32,
$var.auto_converge_initial
),
$dir!(sys::VIR_MIGRATE_PARAM_BANDWIDTH, UInt64, $var.bandwidth),
$dir!(
sys::VIR_MIGRATE_PARAM_BANDWIDTH_POSTCOPY,
UInt64,
$var.bandwidth_postcopy
),
$dir!(sys::VIR_MIGRATE_PARAM_COMPRESSION, String, $var.compression),
$dir!(
sys::VIR_MIGRATE_PARAM_COMPRESSION_MT_DTHREADS,
Int32,
$var.compression_mt_dthreads
),
$dir!(
sys::VIR_MIGRATE_PARAM_COMPRESSION_MT_LEVEL,
Int32,
$var.compression_mt_level
),
$dir!(
sys::VIR_MIGRATE_PARAM_COMPRESSION_MT_THREADS,
Int32,
$var.compression_mt_threads
),
$dir!(
sys::VIR_MIGRATE_PARAM_COMPRESSION_XBZRLE_CACHE,
UInt64,
$var.compression_xbzrle_cache
),
$dir!(
sys::VIR_MIGRATE_PARAM_COMPRESSION_ZLIB_LEVEL,
Int32,
$var.compression_zlib_level
),
$dir!(
sys::VIR_MIGRATE_PARAM_COMPRESSION_ZSTD_LEVEL,
Int32,
$var.compression_zstd_level
),
$dir!(sys::VIR_MIGRATE_PARAM_DEST_NAME, String, $var.dest_name),
$dir!(sys::VIR_MIGRATE_PARAM_DEST_XML, String, $var.dest_xml),
$dir!(sys::VIR_MIGRATE_PARAM_DISKS_PORT, Int32, $var.disks_port),
$dir!(sys::VIR_MIGRATE_PARAM_DISKS_URI, String, $var.disks_uri),
$dir!(
sys::VIR_MIGRATE_PARAM_GRAPHICS_URI,
String,
$var.graphics_uri
),
$dir!(
sys::VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
String,
$var.listen_address
),
$dir!(
sys::VIR_MIGRATE_PARAM_MIGRATE_DISKS,
VecString,
$var.migrate_disks
),
$dir!(
sys::VIR_MIGRATE_PARAM_PARALLEL_CONNECTIONS,
Int32,
$var.parallel_connections
),
$dir!(sys::VIR_MIGRATE_PARAM_PERSIST_XML, String, $var.persist_xml),
$dir!(
sys::VIR_MIGRATE_PARAM_TLS_DESTINATION,
String,
$var.tls_destination
),
$dir!(sys::VIR_MIGRATE_PARAM_URI, String, $var.uri),
]
};
}
#[derive(Clone, Debug, Default)]
pub struct MigrateParameters {
pub auto_converge_increment: Option<i32>,
pub auto_converge_initial: Option<i32>,
pub bandwidth: Option<u64>,
pub bandwidth_postcopy: Option<u64>,
pub compression: Option<String>,
pub compression_mt_dthreads: Option<i32>,
pub compression_mt_level: Option<i32>,
pub compression_mt_threads: Option<i32>,
pub compression_xbzrle_cache: Option<u64>,
pub compression_zlib_level: Option<i32>,
pub compression_zstd_level: Option<i32>,
pub dest_name: Option<String>,
pub dest_xml: Option<String>,
pub disks_port: Option<i32>,
pub disks_uri: Option<String>,
pub graphics_uri: Option<String>,
pub listen_address: Option<String>,
pub migrate_disks: Vec<String>,
pub parallel_connections: Option<i32>,
pub persist_xml: Option<String>,
pub tls_destination: Option<String>,
pub uri: Option<String>,
}
impl MigrateParameters {
pub fn from_vec(vec: Vec<sys::virTypedParameter>) -> MigrateParameters {
let mut ret = MigrateParameters::default();
let fields = migrate_parameters_fields!(param_field_in, ret);
from_params(vec, fields);
ret
}
pub fn to_vec(&self) -> Vec<sys::virTypedParameter> {
let fields = migrate_parameters_fields!(param_field_out, self);
to_params(fields)
}
}
#[derive(Clone, Debug)]
pub struct IPAddress {
pub typed: i64,
pub addr: String,
pub prefix: u64,
}
impl IPAddress {
pub unsafe fn from_ptr(ptr: sys::virDomainIPAddressPtr) -> IPAddress {
IPAddress {
typed: (*ptr).type_ as i64,
addr: c_chars_to_string!((*ptr).addr),
prefix: (*ptr).prefix as u64,
}
}
}
#[derive(Clone, Debug)]
pub struct Interface {
pub name: String,
pub hwaddr: String,
pub naddrs: u64,
pub addrs: Vec<IPAddress>,
}
impl Interface {
pub unsafe fn from_ptr(ptr: sys::virDomainInterfacePtr) -> Interface {
let naddrs = (*ptr).naddrs;
let mut addrs = vec![];
for x in 0..naddrs as isize {
addrs.push(IPAddress::from_ptr((*ptr).addrs.offset(x)));
}
Interface {
name: c_chars_to_string!((*ptr).name),
hwaddr: c_chars_to_string!((*ptr).hwaddr),
naddrs: naddrs as u64,
addrs,
}
}
}
#[derive(Clone, Debug)]
pub struct InterfaceStats {
pub rx_bytes: i64,
pub rx_packets: i64,
pub rx_errs: i64,
pub rx_drop: i64,
pub tx_bytes: i64,
pub tx_packets: i64,
pub tx_errs: i64,
pub tx_drop: i64,
}
impl InterfaceStats {
pub unsafe fn from_ptr(ptr: sys::virDomainInterfaceStatsPtr) -> InterfaceStats {
InterfaceStats {
rx_bytes: (*ptr).rx_bytes,
rx_packets: (*ptr).rx_packets,
rx_errs: (*ptr).rx_errs,
rx_drop: (*ptr).rx_drop,
tx_bytes: (*ptr).tx_bytes,
tx_packets: (*ptr).tx_packets,
tx_errs: (*ptr).tx_errs,
tx_drop: (*ptr).tx_drop,
}
}
}
#[derive(Clone, Debug)]
pub struct MemoryStat {
pub tag: u32,
pub val: u64,
}
impl MemoryStat {
pub unsafe fn from_ptr(ptr: *const sys::virDomainMemoryStatStruct) -> MemoryStat {
MemoryStat {
tag: (*ptr).tag as u32,
val: (*ptr).val,
}
}
}
#[derive(Clone, Debug, Default)]
pub struct JobStats {
pub r#type: i32,
pub auto_converge_throttle: Option<i32>,
pub compression_bytes: Option<u64>,
pub compression_cache: Option<u64>,
pub compression_cache_misses: Option<u64>,
pub compression_overflow: Option<u64>,
pub compression_pages: Option<u64>,
pub data_processed: Option<u64>,
pub data_remaining: Option<u64>,
pub data_total: Option<u64>,
pub disk_bps: Option<u64>,
pub disk_processed: Option<u64>,
pub disk_remaining: Option<u64>,
pub disk_temp_total: Option<u64>,
pub disk_temp_used: Option<u64>,
pub disk_total: Option<u64>,
pub downtime: Option<u64>,
pub downtime_net: Option<u64>,
pub error_message: Option<String>,
pub mem_bps: Option<u64>,
pub mem_constant: Option<u64>,
pub mem_dirty_rate: Option<u64>,
pub mem_iteration: Option<u64>,
pub mem_normal: Option<u64>,
pub mem_normal_bytes: Option<u64>,
pub mem_page_size: Option<u64>,
pub mem_postcopy_reqs: Option<u64>,
pub mem_processed: Option<u64>,
pub mem_remaining: Option<u64>,
pub mem_total: Option<u64>,
pub operation: Option<i32>,
pub setup_time: Option<u64>,
pub success: Option<bool>,
pub time_elapsed: Option<u64>,
pub time_elapsed_net: Option<u64>,
pub time_remaining: Option<u64>,
}
macro_rules! job_stats_fields {
($dir:ident, $var:ident) => {
vec![
$dir!(
sys::VIR_DOMAIN_JOB_AUTO_CONVERGE_THROTTLE,
Int32,
$var.auto_converge_throttle
),
$dir!(
sys::VIR_DOMAIN_JOB_COMPRESSION_BYTES,
UInt64,
$var.compression_bytes
),
$dir!(
sys::VIR_DOMAIN_JOB_COMPRESSION_CACHE,
UInt64,
$var.compression_cache
),
$dir!(
sys::VIR_DOMAIN_JOB_COMPRESSION_CACHE_MISSES,
UInt64,
$var.compression_cache_misses
),
$dir!(
sys::VIR_DOMAIN_JOB_COMPRESSION_OVERFLOW,
UInt64,
$var.compression_overflow
),
$dir!(
sys::VIR_DOMAIN_JOB_COMPRESSION_PAGES,
UInt64,
$var.compression_pages
),
$dir!(
sys::VIR_DOMAIN_JOB_DATA_PROCESSED,
UInt64,
$var.data_processed
),
$dir!(
sys::VIR_DOMAIN_JOB_DATA_REMAINING,
UInt64,
$var.data_remaining
),
$dir!(sys::VIR_DOMAIN_JOB_DATA_TOTAL, UInt64, $var.data_total),
$dir!(sys::VIR_DOMAIN_JOB_DISK_BPS, UInt64, $var.disk_bps),
$dir!(
sys::VIR_DOMAIN_JOB_DISK_PROCESSED,
UInt64,
$var.disk_processed
),
$dir!(
sys::VIR_DOMAIN_JOB_DISK_REMAINING,
UInt64,
$var.disk_remaining
),
$dir!(
sys::VIR_DOMAIN_JOB_DISK_TEMP_TOTAL,
UInt64,
$var.disk_temp_total
),
$dir!(
sys::VIR_DOMAIN_JOB_DISK_TEMP_USED,
UInt64,
$var.disk_temp_used
),
$dir!(sys::VIR_DOMAIN_JOB_DISK_TOTAL, UInt64, $var.disk_total),
$dir!(sys::VIR_DOMAIN_JOB_DOWNTIME, UInt64, $var.downtime),
$dir!(sys::VIR_DOMAIN_JOB_DOWNTIME_NET, UInt64, $var.downtime_net),
$dir!(sys::VIR_DOMAIN_JOB_ERRMSG, String, $var.error_message),
$dir!(sys::VIR_DOMAIN_JOB_MEMORY_BPS, UInt64, $var.mem_bps),
$dir!(
sys::VIR_DOMAIN_JOB_MEMORY_CONSTANT,
UInt64,
$var.mem_constant
),
$dir!(
sys::VIR_DOMAIN_JOB_MEMORY_DIRTY_RATE,
UInt64,
$var.mem_dirty_rate
),
$dir!(
sys::VIR_DOMAIN_JOB_MEMORY_ITERATION,
UInt64,
$var.mem_iteration
),
$dir!(sys::VIR_DOMAIN_JOB_MEMORY_NORMAL, UInt64, $var.mem_normal),
$dir!(
sys::VIR_DOMAIN_JOB_MEMORY_NORMAL_BYTES,
UInt64,
$var.mem_normal_bytes
),
$dir!(
sys::VIR_DOMAIN_JOB_MEMORY_PAGE_SIZE,
UInt64,
$var.mem_page_size
),
$dir!(
sys::VIR_DOMAIN_JOB_MEMORY_POSTCOPY_REQS,
UInt64,
$var.mem_postcopy_reqs
),
$dir!(
sys::VIR_DOMAIN_JOB_MEMORY_PROCESSED,
UInt64,
$var.mem_processed
),
$dir!(
sys::VIR_DOMAIN_JOB_MEMORY_REMAINING,
UInt64,
$var.mem_remaining
),
$dir!(sys::VIR_DOMAIN_JOB_MEMORY_TOTAL, UInt64, $var.mem_total),
$dir!(sys::VIR_DOMAIN_JOB_OPERATION, Int32, $var.operation),
$dir!(sys::VIR_DOMAIN_JOB_SETUP_TIME, UInt64, $var.setup_time),
$dir!(sys::VIR_DOMAIN_JOB_SUCCESS, Bool, $var.success),
$dir!(sys::VIR_DOMAIN_JOB_TIME_ELAPSED, UInt64, $var.time_elapsed),
$dir!(
sys::VIR_DOMAIN_JOB_TIME_ELAPSED_NET,
UInt64,
$var.time_elapsed_net
),
$dir!(
sys::VIR_DOMAIN_JOB_TIME_REMAINING,
UInt64,
$var.time_remaining
),
]
};
}
impl From<(i32, Vec<sys::virTypedParameter>)> for JobStats {
fn from((r#type, params): (i32, Vec<sys::virTypedParameter>)) -> Self {
let mut stats = Self {
r#type,
..Default::default()
};
let fields = job_stats_fields!(param_field_in, stats);
from_params(params, fields);
stats
}
}
#[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,
pub cpu_shares: Option<u64>,
pub vcpu_bw: SchedBandwidth,
pub emulator_bw: SchedBandwidth,
pub global_bw: SchedBandwidth,
pub iothread_bw: SchedBandwidth,
pub weight: Option<u32>,
pub cap: Option<u32>,
pub reservation: Option<i64>,
pub limit: Option<i64>,
pub shares: Option<i32>,
}
macro_rules! scheduler_info_fields {
($dir:ident, $var:ident) => {
vec![
$dir!(
sys::VIR_DOMAIN_SCHEDULER_CPU_SHARES,
UInt64,
$var.cpu_shares
),
$dir!(
sys::VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
UInt64,
$var.vcpu_bw.period
),
$dir!(
sys::VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
Int64,
$var.vcpu_bw.quota
),
$dir!(
sys::VIR_DOMAIN_SCHEDULER_EMULATOR_PERIOD,
UInt64,
$var.emulator_bw.period
),
$dir!(
sys::VIR_DOMAIN_SCHEDULER_EMULATOR_QUOTA,
Int64,
$var.emulator_bw.quota
),
$dir!(
sys::VIR_DOMAIN_SCHEDULER_GLOBAL_PERIOD,
UInt64,
$var.global_bw.period
),
$dir!(
sys::VIR_DOMAIN_SCHEDULER_GLOBAL_QUOTA,
Int64,
$var.global_bw.quota
),
$dir!(
sys::VIR_DOMAIN_SCHEDULER_IOTHREAD_PERIOD,
UInt64,
$var.iothread_bw.period
),
$dir!(
sys::VIR_DOMAIN_SCHEDULER_IOTHREAD_QUOTA,
Int64,
$var.iothread_bw.quota
),
$dir!(sys::VIR_DOMAIN_SCHEDULER_WEIGHT, UInt32, $var.weight),
$dir!(sys::VIR_DOMAIN_SCHEDULER_CAP, UInt32, $var.cap),
$dir!(
sys::VIR_DOMAIN_SCHEDULER_RESERVATION,
Int64,
$var.reservation
),
$dir!(sys::VIR_DOMAIN_SCHEDULER_LIMIT, Int64, $var.limit),
$dir!(sys::VIR_DOMAIN_SCHEDULER_SHARES, Int32, $var.shares),
]
};
}
impl SchedulerInfo {
pub fn from_vec(vec: Vec<sys::virTypedParameter>, scheduler_type: String) -> SchedulerInfo {
let mut ret = SchedulerInfo {
scheduler_type,
..Default::default()
};
let fields = scheduler_info_fields!(param_field_in, ret);
from_params(vec, fields);
ret
}
pub fn to_vec(&self) -> Vec<sys::virTypedParameter> {
let fields = scheduler_info_fields!(param_field_out, self);
to_params(fields)
}
}
#[derive(Debug)]
pub struct Domain {
ptr: Option<sys::virDomainPtr>,
}
unsafe impl Send for Domain {}
unsafe impl Sync for Domain {}
impl Drop for Domain {
fn drop(&mut self) {
if self.ptr.is_some() {
if let Err(e) = self.free() {
panic!("Unable to drop memory for Domain: {e}")
}
}
}
}
impl Clone for Domain {
fn clone(&self) -> Self {
self.add_ref().unwrap()
}
}
impl Domain {
pub unsafe fn from_ptr(ptr: sys::virDomainPtr) -> Domain {
Domain { ptr: Some(ptr) }
}
fn add_ref(&self) -> Result<Domain, Error> {
unsafe {
if sys::virDomainRef(self.as_ptr()) == -1 {
return Err(Error::last_error());
}
}
Ok(unsafe { Domain::from_ptr(self.as_ptr()) })
}
pub fn as_ptr(&self) -> sys::virDomainPtr {
self.ptr.unwrap()
}
pub fn get_connect(&self) -> Result<Connect, Error> {
let ptr = unsafe { sys::virDomainGetConnect(self.as_ptr()) };
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { Connect::from_ptr(ptr) })
}
pub fn lookup_by_id(conn: &Connect, id: u32) -> Result<Domain, Error> {
let ptr = unsafe { sys::virDomainLookupByID(conn.as_ptr(), id as libc::c_int) };
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { Domain::from_ptr(ptr) })
}
pub fn lookup_by_name(conn: &Connect, id: &str) -> Result<Domain, Error> {
let id_buf = CString::new(id).unwrap();
let ptr = unsafe { sys::virDomainLookupByName(conn.as_ptr(), id_buf.as_ptr()) };
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { Domain::from_ptr(ptr) })
}
pub fn lookup_by_uuid(conn: &Connect, uuid: Uuid) -> Result<Domain, Error> {
let ptr = unsafe { sys::virDomainLookupByUUID(conn.as_ptr(), uuid.as_bytes().as_ptr()) };
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { Domain::from_ptr(ptr) })
}
pub fn lookup_by_uuid_string(conn: &Connect, uuid: &str) -> Result<Domain, Error> {
let uuid_buf = CString::new(uuid).unwrap();
let ptr = unsafe { sys::virDomainLookupByUUIDString(conn.as_ptr(), uuid_buf.as_ptr()) };
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { Domain::from_ptr(ptr) })
}
pub fn get_state(&self) -> Result<(sys::virDomainState, i32), Error> {
let mut state: libc::c_int = -1;
let mut reason: libc::c_int = -1;
let ret = unsafe { sys::virDomainGetState(self.as_ptr(), &mut state, &mut reason, 0) };
if ret == -1 {
return Err(Error::last_error());
}
Ok((state as sys::virDomainState, reason))
}
pub fn get_name(&self) -> Result<String, Error> {
let n = unsafe { sys::virDomainGetName(self.as_ptr()) };
if n.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { c_chars_to_string!(n, nofree) })
}
pub fn get_os_type(&self) -> Result<String, Error> {
let n = unsafe { sys::virDomainGetOSType(self.as_ptr()) };
if n.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { c_chars_to_string!(n) })
}
pub fn get_hostname(&self, flags: u32) -> Result<String, Error> {
let n = unsafe { sys::virDomainGetHostname(self.as_ptr(), flags as libc::c_uint) };
if n.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { c_chars_to_string!(n) })
}
pub fn get_uuid(&self) -> Result<Uuid, Error> {
let mut uuid: [libc::c_uchar; sys::VIR_UUID_BUFLEN as usize] =
[0; sys::VIR_UUID_BUFLEN as usize];
let ret = unsafe { sys::virDomainGetUUID(self.as_ptr(), uuid.as_mut_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(Uuid::from_bytes(uuid))
}
pub fn get_uuid_string(&self) -> Result<String, Error> {
let mut uuid: [libc::c_char; sys::VIR_UUID_STRING_BUFLEN as usize] =
[0; sys::VIR_UUID_STRING_BUFLEN as usize];
let ret = unsafe { sys::virDomainGetUUIDString(self.as_ptr(), uuid.as_mut_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(unsafe { c_chars_to_string!(uuid.as_ptr(), nofree) })
}
pub fn get_id(&self) -> Option<u32> {
let ret = unsafe { sys::virDomainGetID(self.as_ptr()) };
if ret as i32 == -1 {
return None;
}
Some(ret)
}
pub fn get_xml_desc(&self, flags: sys::virDomainCreateFlags) -> Result<String, Error> {
let xml = unsafe { sys::virDomainGetXMLDesc(self.as_ptr(), flags) };
if xml.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { c_chars_to_string!(xml) })
}
pub fn create(&self) -> Result<u32, Error> {
let ret = unsafe { sys::virDomainCreate(self.as_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn create_with_flags(&self, flags: sys::virDomainCreateFlags) -> Result<u32, Error> {
let res = unsafe { sys::virDomainCreateWithFlags(self.as_ptr(), flags as libc::c_uint) };
if res == -1 {
return Err(Error::last_error());
}
Ok(res as u32)
}
pub fn get_info(&self) -> Result<DomainInfo, Error> {
let mut pinfo = mem::MaybeUninit::uninit();
let res = unsafe { sys::virDomainGetInfo(self.as_ptr(), pinfo.as_mut_ptr()) };
if res == -1 {
return Err(Error::last_error());
}
Ok(unsafe { DomainInfo::from_ptr(&mut pinfo.assume_init()) })
}
pub fn create_xml(
conn: &Connect,
xml: &str,
flags: sys::virDomainCreateFlags,
) -> Result<Domain, Error> {
let xml_buf = CString::new(xml).unwrap();
let ptr = unsafe {
sys::virDomainCreateXML(conn.as_ptr(), xml_buf.as_ptr(), flags as libc::c_uint)
};
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { Domain::from_ptr(ptr) })
}
pub fn define_xml(conn: &Connect, xml: &str) -> Result<Domain, Error> {
let xml_buf = CString::new(xml).unwrap();
let ptr = unsafe { sys::virDomainDefineXML(conn.as_ptr(), xml_buf.as_ptr()) };
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { Domain::from_ptr(ptr) })
}
pub fn define_xml_flags(
conn: &Connect,
xml: &str,
flags: sys::virDomainDefineFlags,
) -> Result<Domain, Error> {
let xml_buf = CString::new(xml).unwrap();
let ptr = unsafe {
sys::virDomainDefineXMLFlags(conn.as_ptr(), xml_buf.as_ptr(), flags as libc::c_uint)
};
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { Domain::from_ptr(ptr) })
}
pub fn destroy(&self) -> Result<(), Error> {
let ret = unsafe { sys::virDomainDestroy(self.as_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(())
}
pub fn reset(&self) -> Result<u32, Error> {
let ret = unsafe { sys::virDomainReset(self.as_ptr(), 0) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn destroy_flags(&self, flags: sys::virDomainDestroyFlagsValues) -> Result<u32, Error> {
let ret = unsafe { sys::virDomainDestroyFlags(self.as_ptr(), flags) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn shutdown(&self) -> Result<u32, Error> {
let ret = unsafe { sys::virDomainShutdown(self.as_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn shutdown_flags(&self, flags: sys::virDomainShutdownFlagValues) -> Result<u32, Error> {
let ret = unsafe { sys::virDomainShutdownFlags(self.as_ptr(), flags as libc::c_uint) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn reboot(&self, flags: sys::virDomainRebootFlagValues) -> Result<(), Error> {
let ret = unsafe { sys::virDomainReboot(self.as_ptr(), flags) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(())
}
pub fn suspend(&self) -> Result<u32, Error> {
let ret = unsafe { sys::virDomainSuspend(self.as_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn resume(&self) -> Result<u32, Error> {
let ret = unsafe { sys::virDomainResume(self.as_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn pm_wakeup(&self, flags: u32) -> Result<u32, Error> {
let ret = unsafe { sys::virDomainPMWakeup(self.as_ptr(), flags as libc::c_uint) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn is_active(&self) -> Result<bool, Error> {
let ret = unsafe { sys::virDomainIsActive(self.as_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret == 1)
}
pub fn is_persistent(&self) -> Result<bool, Error> {
let ret = unsafe { sys::virDomainIsPersistent(self.as_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret == 1)
}
pub fn undefine(&self) -> Result<(), Error> {
let ret = unsafe { sys::virDomainUndefine(self.as_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(())
}
pub fn undefine_flags(&self, flags: sys::virDomainUndefineFlagsValues) -> Result<(), Error> {
let ret = unsafe { sys::virDomainUndefineFlags(self.as_ptr(), flags) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(())
}
pub fn free(&mut self) -> Result<(), Error> {
let ret = unsafe { sys::virDomainFree(self.as_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
self.ptr = None;
Ok(())
}
pub fn is_updated(&self) -> Result<bool, Error> {
let ret = unsafe { sys::virDomainIsUpdated(self.as_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret == 1)
}
pub fn get_autostart(&self) -> Result<bool, Error> {
let mut autostart: libc::c_int = 0;
let ret = unsafe { sys::virDomainGetAutostart(self.as_ptr(), &mut autostart) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(autostart == 1)
}
pub fn set_autostart(&self, autostart: bool) -> Result<bool, Error> {
let ret = unsafe { sys::virDomainSetAutostart(self.as_ptr(), autostart as libc::c_int) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret == 1)
}
pub fn set_max_memory(&self, memory: u64) -> Result<bool, Error> {
let ret = unsafe { sys::virDomainSetMaxMemory(self.as_ptr(), memory as libc::c_ulong) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret == 1)
}
pub fn get_max_memory(&self) -> Result<u64, Error> {
let ret = unsafe { sys::virDomainGetMaxMemory(self.as_ptr()) };
if ret == 0 {
return Err(Error::last_error());
}
Ok(c_ulong_to_u64(ret))
}
pub fn get_max_vcpus(&self) -> Result<u64, Error> {
let ret = unsafe { sys::virDomainGetMaxVcpus(self.as_ptr()) };
if ret == 0 {
return Err(Error::last_error());
}
Ok(ret as u64)
}
pub fn set_memory(&self, memory: u64) -> Result<bool, Error> {
let ret = unsafe { sys::virDomainSetMemory(self.as_ptr(), memory as libc::c_ulong) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret == 1)
}
pub fn set_memory_flags(
&self,
memory: u64,
flags: sys::virDomainMemoryModFlags,
) -> Result<bool, Error> {
let ret = unsafe {
sys::virDomainSetMemoryFlags(
self.as_ptr(),
memory as libc::c_ulong,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret == 1)
}
pub fn set_memory_stats_period(
&self,
period: i32,
flags: sys::virDomainMemoryModFlags,
) -> Result<bool, Error> {
let ret = unsafe {
sys::virDomainSetMemoryStatsPeriod(
self.as_ptr(),
period as libc::c_int,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret == 1)
}
pub fn set_vcpus(&self, vcpus: u32) -> Result<bool, Error> {
let ret = unsafe { sys::virDomainSetVcpus(self.as_ptr(), vcpus as libc::c_uint) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret == 1)
}
pub fn set_vcpus_flags(
&self,
vcpus: u32,
flags: sys::virDomainVcpuFlags,
) -> Result<bool, Error> {
let ret = unsafe {
sys::virDomainSetVcpusFlags(self.as_ptr(), vcpus as libc::c_uint, flags as libc::c_uint)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret == 1)
}
pub fn domain_restore(conn: &Connect, path: &str) -> Result<(), Error> {
let path_buf = CString::new(path).unwrap();
let ret = unsafe { sys::virDomainRestore(conn.as_ptr(), path_buf.as_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(())
}
pub fn domain_restore_flags(
conn: &Connect,
path: &str,
dxml: Option<&str>,
flags: sys::virDomainSaveRestoreFlags,
) -> Result<(), Error> {
let path_buf = CString::new(path).unwrap();
let dxml_buf = some_string_to_cstring!(dxml);
let ret = unsafe {
sys::virDomainRestoreFlags(
conn.as_ptr(),
path_buf.as_ptr(),
some_cstring_to_c_chars!(dxml_buf),
flags,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(())
}
pub fn get_vcpus_flags(&self, flags: sys::virDomainVcpuFlags) -> Result<u32, Error> {
let ret = unsafe { sys::virDomainGetVcpusFlags(self.as_ptr(), flags as libc::c_uint) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn migrate_set_max_speed(&self, bandwidth: u64, flags: u32) -> Result<u32, Error> {
let ret = unsafe {
sys::virDomainMigrateSetMaxSpeed(
self.as_ptr(),
bandwidth as libc::c_ulong,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn migrate_get_max_speed(&self, flags: u32) -> Result<u64, Error> {
let mut bandwidth: libc::c_ulong = 0;
let ret = unsafe {
sys::virDomainMigrateGetMaxSpeed(self.as_ptr(), &mut bandwidth, flags as libc::c_uint)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(c_ulong_to_u64(bandwidth))
}
pub fn migrate_set_compression_cache(&self, size: u64, flags: u32) -> Result<u32, Error> {
let ret = unsafe {
sys::virDomainMigrateSetCompressionCache(
self.as_ptr(),
size as libc::c_ulonglong,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn migrate_get_compression_cache(&self, flags: u32) -> Result<u64, Error> {
let mut size: libc::c_ulonglong = 0;
let ret = unsafe {
sys::virDomainMigrateGetCompressionCache(
self.as_ptr(),
&mut size,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(size)
}
pub fn migrate_set_max_downtime(&self, downtime: u64, flags: u32) -> Result<u32, Error> {
let ret = unsafe {
sys::virDomainMigrateSetMaxDowntime(
self.as_ptr(),
downtime as libc::c_ulonglong,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn set_time(&self, seconds: i64, nseconds: i32, flags: u32) -> Result<u32, Error> {
let ret = unsafe {
sys::virDomainSetTime(
self.as_ptr(),
seconds as libc::c_longlong,
nseconds as libc::c_uint,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn get_time(&self, flags: u32) -> Result<(i64, i32), Error> {
let mut seconds: libc::c_longlong = 0;
let mut nseconds: libc::c_uint = 0;
let ret = unsafe {
sys::virDomainGetTime(
self.as_ptr(),
&mut seconds,
&mut nseconds,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok((seconds, nseconds as i32))
}
pub fn get_block_info(&self, disk: &str, flags: u32) -> Result<BlockInfo, Error> {
let mut pinfo = mem::MaybeUninit::uninit();
let disk_buf = CString::new(disk).unwrap();
let ret = unsafe {
sys::virDomainGetBlockInfo(
self.as_ptr(),
disk_buf.as_ptr(),
pinfo.as_mut_ptr(),
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(unsafe { BlockInfo::from_ptr(&mut pinfo.assume_init()) })
}
pub fn get_block_stats(&self, disk: &str) -> Result<BlockStats, Error> {
let mut pinfo = mem::MaybeUninit::uninit();
let disk_buf = CString::new(disk).unwrap();
let ret = unsafe {
sys::virDomainBlockStats(
self.as_ptr(),
disk_buf.as_ptr(),
pinfo.as_mut_ptr(),
mem::size_of::<sys::virDomainBlockStatsStruct>(),
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(unsafe { BlockStats::from_ptr(&mut pinfo.assume_init()) })
}
pub fn pin_vcpu(&self, vcpu: u32, cpumap: &[u8]) -> Result<u32, Error> {
let ret = unsafe {
sys::virDomainPinVcpu(
self.as_ptr(),
vcpu as libc::c_uint,
cpumap.as_ptr() as *mut _,
cpumap.len() as libc::c_int,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn pin_vcpu_flags(&self, vcpu: u32, cpumap: &[u8], flags: u32) -> Result<u32, Error> {
let ret = unsafe {
sys::virDomainPinVcpuFlags(
self.as_ptr(),
vcpu as libc::c_uint,
cpumap.as_ptr() as *mut _,
cpumap.len() as libc::c_int,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn pin_emulator(&self, cpumap: &[u8], flags: u32) -> Result<u32, Error> {
let ret = unsafe {
sys::virDomainPinEmulator(
self.as_ptr(),
cpumap.as_ptr() as *mut _,
cpumap.len() as libc::c_int,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn rename(&self, new_name: &str, flags: u32) -> Result<u32, Error> {
let new_name_buf = CString::new(new_name).unwrap();
let ret = unsafe {
sys::virDomainRename(self.as_ptr(), new_name_buf.as_ptr(), flags as libc::c_uint)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn set_user_password(&self, user: &str, password: &str, flags: u32) -> Result<u32, Error> {
let user_buf = CString::new(user).unwrap();
let password_buf = CString::new(password).unwrap();
let ret = unsafe {
sys::virDomainSetUserPassword(
self.as_ptr(),
user_buf.as_ptr(),
password_buf.as_ptr(),
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn set_block_threshold(&self, dev: &str, threshold: u64, flags: u32) -> Result<u32, Error> {
let dev_buf = CString::new(dev).unwrap();
let ret = unsafe {
sys::virDomainSetBlockThreshold(
self.as_ptr(),
dev_buf.as_ptr(),
threshold as libc::c_ulonglong,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn open_graphics(&self, idx: u32, fd: i32, flags: u32) -> Result<u32, Error> {
let ret = unsafe {
sys::virDomainOpenGraphics(
self.as_ptr(),
idx as libc::c_uint,
fd as libc::c_int,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn open_graphics_fd(&self, idx: u32, flags: u32) -> Result<u32, Error> {
let ret = unsafe {
sys::virDomainOpenGraphicsFD(self.as_ptr(), idx as libc::c_uint, flags as libc::c_uint)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn open_channel(
&self,
name: Option<&str>,
stream: &Stream,
flags: u32,
) -> Result<u32, Error> {
let name_buf = some_string_to_cstring!(name);
let ret = unsafe {
sys::virDomainOpenChannel(
self.as_ptr(),
some_cstring_to_c_chars!(name_buf),
stream.as_ptr(),
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn open_console(
&self,
name: Option<&str>,
stream: &Stream,
flags: u32,
) -> Result<u32, Error> {
let name_buf = some_string_to_cstring!(name);
let ret = unsafe {
sys::virDomainOpenConsole(
self.as_ptr(),
some_cstring_to_c_chars!(name_buf),
stream.as_ptr(),
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn interface_addresses(
&self,
source: sys::virDomainInterfaceAddressesSource,
flags: u32,
) -> Result<Vec<Interface>, Error> {
let mut addresses: *mut sys::virDomainInterfacePtr = ptr::null_mut();
let size = unsafe {
sys::virDomainInterfaceAddresses(self.as_ptr(), &mut addresses, source, flags)
};
if size == -1 {
return Err(Error::last_error());
}
let mut array: Vec<Interface> = Vec::new();
for x in 0..size as isize {
array.push(unsafe { Interface::from_ptr(*addresses.offset(x)) });
}
unsafe { libc::free(addresses as *mut libc::c_void) };
Ok(array)
}
pub fn interface_stats(&self, path: &str) -> Result<InterfaceStats, Error> {
let mut pinfo = mem::MaybeUninit::uninit();
let path_buf = CString::new(path).unwrap();
let ret = unsafe {
sys::virDomainInterfaceStats(
self.as_ptr(),
path_buf.as_ptr(),
pinfo.as_mut_ptr(),
mem::size_of::<sys::virDomainInterfaceStatsStruct>(),
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(unsafe { InterfaceStats::from_ptr(&mut pinfo.assume_init()) })
}
pub fn memory_stats(&self, flags: u32) -> Result<Vec<MemoryStat>, Error> {
let mut pinfo: Vec<sys::virDomainMemoryStatStruct> =
Vec::with_capacity(sys::VIR_DOMAIN_MEMORY_STAT_NR as usize);
let ret = unsafe {
sys::virDomainMemoryStats(
self.as_ptr(),
pinfo.as_mut_ptr(),
sys::VIR_DOMAIN_MEMORY_STAT_NR,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
unsafe { pinfo.set_len(ret as usize) };
let mut stats: Vec<MemoryStat> = Vec::with_capacity(ret as usize);
for x in pinfo.iter().take(ret as usize) {
stats.push(unsafe { MemoryStat::from_ptr(x) });
}
Ok(stats)
}
pub fn get_job_stats(&self, flags: sys::virDomainGetJobStatsFlags) -> Result<JobStats, Error> {
let mut r#type: libc::c_int = 0;
let mut nparams: libc::c_int = 0;
let mut params: sys::virTypedParameterPtr = ptr::null_mut();
let ret = unsafe {
sys::virDomainGetJobStats(
self.as_ptr(),
&mut r#type,
&mut params,
&mut nparams,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
let res: Vec<sys::virTypedParameter> =
unsafe { Vec::from_raw_parts(params, nparams as usize, nparams as usize) };
Ok((r#type, res).into())
}
pub fn get_job_info(&self) -> Result<JobStats, Error> {
unsafe {
let mut job_info = mem::MaybeUninit::uninit();
let ret = sys::virDomainGetJobInfo(self.as_ptr(), job_info.as_mut_ptr());
if ret == -1 {
return Err(Error::last_error());
}
let ptr: sys::virDomainJobInfoPtr = &mut job_info.assume_init();
Ok(JobStats {
r#type: (*ptr).type_,
time_elapsed: Some((*ptr).timeElapsed as u64),
time_remaining: Some((*ptr).timeRemaining as u64),
data_total: Some((*ptr).dataTotal as u64),
data_processed: Some((*ptr).dataProcessed as u64),
data_remaining: Some((*ptr).dataRemaining as u64),
mem_total: Some((*ptr).memTotal as u64),
mem_processed: Some((*ptr).memProcessed as u64),
mem_remaining: Some((*ptr).memRemaining as u64),
disk_total: Some((*ptr).fileTotal as u64),
disk_processed: Some((*ptr).fileProcessed as u64),
disk_remaining: Some((*ptr).fileRemaining as u64),
..Default::default()
})
}
}
pub fn save_image_get_xml_desc(
conn: &Connect,
file: &str,
flags: u32,
) -> Result<String, Error> {
let file_buf = CString::new(file).unwrap();
let ptr = unsafe {
sys::virDomainSaveImageGetXMLDesc(
conn.as_ptr(),
file_buf.as_ptr(),
flags as libc::c_uint,
)
};
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { c_chars_to_string!(ptr) })
}
pub fn save_image_define_xml(
conn: &Connect,
file: &str,
dxml: &str,
flags: u32,
) -> Result<u32, Error> {
let file_buf = CString::new(file).unwrap();
let dxml_buf = CString::new(dxml).unwrap();
let ret = unsafe {
sys::virDomainSaveImageDefineXML(
conn.as_ptr(),
file_buf.as_ptr(),
dxml_buf.as_ptr(),
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn attach_device(&self, xml: &str) -> Result<u32, Error> {
let xml_buf = CString::new(xml).unwrap();
let ret = unsafe { sys::virDomainAttachDevice(self.as_ptr(), xml_buf.as_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn attach_device_flags(&self, xml: &str, flags: u32) -> Result<u32, Error> {
let xml_buf = CString::new(xml).unwrap();
let ret = unsafe {
sys::virDomainAttachDeviceFlags(self.as_ptr(), xml_buf.as_ptr(), flags as libc::c_uint)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn detach_device(&self, xml: &str) -> Result<u32, Error> {
let xml_buf = CString::new(xml).unwrap();
let ret = unsafe { sys::virDomainDetachDevice(self.as_ptr(), xml_buf.as_ptr()) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn detach_device_flags(&self, xml: &str, flags: u32) -> Result<u32, Error> {
let xml_buf = CString::new(xml).unwrap();
let ret = unsafe {
sys::virDomainDetachDeviceFlags(self.as_ptr(), xml_buf.as_ptr(), flags as libc::c_uint)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn update_device_flags(&self, xml: &str, flags: u32) -> Result<u32, Error> {
let xml_buf = CString::new(xml).unwrap();
let ret = unsafe {
sys::virDomainUpdateDeviceFlags(self.as_ptr(), xml_buf.as_ptr(), flags as libc::c_uint)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn managed_save(&self, flags: u32) -> Result<u32, Error> {
let ret = unsafe { sys::virDomainManagedSave(self.as_ptr(), flags as libc::c_uint) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn has_managed_save(&self, flags: u32) -> Result<bool, Error> {
let ret =
unsafe { sys::virDomainHasManagedSaveImage(self.as_ptr(), flags as libc::c_uint) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret == 1)
}
pub fn managed_save_remove(&self, flags: u32) -> Result<u32, Error> {
let ret = unsafe { sys::virDomainManagedSaveRemove(self.as_ptr(), flags as libc::c_uint) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn core_dump(&self, to: &str, flags: u32) -> Result<u32, Error> {
let to_buf = CString::new(to).unwrap();
let ret = unsafe {
sys::virDomainCoreDump(self.as_ptr(), to_buf.as_ptr(), flags as libc::c_uint)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn core_dump_with_format(&self, to: &str, format: u32, flags: u32) -> Result<u32, Error> {
let to_buf = CString::new(to).unwrap();
let ret = unsafe {
sys::virDomainCoreDumpWithFormat(
self.as_ptr(),
to_buf.as_ptr(),
format as libc::c_uint,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn set_metadata(
&self,
kind: i32,
metadata: Option<&str>,
key: Option<&str>,
uri: Option<&str>,
flags: u32,
) -> Result<u32, Error> {
let metadata_buf = some_string_to_cstring!(metadata);
let key_buf = some_string_to_cstring!(key);
let uri_buf = some_string_to_cstring!(uri);
let ret = unsafe {
sys::virDomainSetMetadata(
self.as_ptr(),
kind as libc::c_int,
some_cstring_to_c_chars!(metadata_buf),
some_cstring_to_c_chars!(key_buf),
some_cstring_to_c_chars!(uri_buf),
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn get_metadata(&self, kind: i32, uri: Option<&str>, flags: u32) -> Result<String, Error> {
let uri_buf = some_string_to_cstring!(uri);
let n = unsafe {
sys::virDomainGetMetadata(
self.as_ptr(),
kind as libc::c_int,
some_cstring_to_c_chars!(uri_buf),
flags as libc::c_uint,
)
};
if n.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { c_chars_to_string!(n) })
}
pub fn block_resize(&self, disk: &str, size: u64, flags: u32) -> Result<u32, Error> {
let disk_buf = CString::new(disk).unwrap();
let ret = unsafe {
sys::virDomainBlockResize(
self.as_ptr(),
disk_buf.as_ptr(),
size as libc::c_ulonglong,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn get_memory_parameters(&self, flags: u32) -> Result<MemoryParameters, Error> {
let mut nparams: libc::c_int = 0;
let ret = unsafe {
sys::virDomainGetMemoryParameters(
self.as_ptr(),
ptr::null_mut(),
&mut nparams,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
let mut params: Vec<sys::virTypedParameter> = Vec::with_capacity(nparams as usize);
let ret = unsafe {
sys::virDomainGetMemoryParameters(
self.as_ptr(),
params.as_mut_ptr(),
&mut nparams,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
unsafe { params.set_len(nparams as usize) };
Ok(MemoryParameters::from_vec(params))
}
pub fn set_memory_parameters(
&self,
params: MemoryParameters,
flags: u32,
) -> Result<u32, Error> {
let mut cparams = params.to_vec();
let ret = unsafe {
sys::virDomainSetMemoryParameters(
self.as_ptr(),
cparams.as_mut_ptr(),
cparams.len() as libc::c_int,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn migrate(
&self,
dconn: &Connect,
flags: u32,
dname: Option<&str>,
uri: Option<&str>,
bandwidth: u64,
) -> Result<Domain, Error> {
let dname_buf = some_string_to_cstring!(dname);
let uri_buf = some_string_to_cstring!(uri);
let ptr = unsafe {
sys::virDomainMigrate(
self.as_ptr(),
dconn.as_ptr(),
flags as libc::c_ulong,
some_cstring_to_c_chars!(dname_buf),
some_cstring_to_c_chars!(uri_buf),
bandwidth as libc::c_ulong,
)
};
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { Domain::from_ptr(ptr) })
}
pub fn migrate2(
&self,
dconn: &Connect,
dxml: Option<&str>,
flags: u32,
dname: Option<&str>,
uri: Option<&str>,
bandwidth: u64,
) -> Result<Domain, Error> {
let dxml_buf = some_string_to_cstring!(dxml);
let dname_buf = some_string_to_cstring!(dname);
let uri_buf = some_string_to_cstring!(uri);
let ptr = unsafe {
sys::virDomainMigrate2(
self.as_ptr(),
dconn.as_ptr(),
some_cstring_to_c_chars!(dxml_buf),
flags as libc::c_ulong,
some_cstring_to_c_chars!(dname_buf),
some_cstring_to_c_chars!(uri_buf),
bandwidth as libc::c_ulong,
)
};
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { Domain::from_ptr(ptr) })
}
pub fn migrate3(
&self,
dconn: &Connect,
parameters: MigrateParameters,
flags: u32,
) -> Result<Domain, Error> {
let params = parameters.to_vec();
let ptr = unsafe {
sys::virDomainMigrate3(
self.as_ptr(),
dconn.as_ptr(),
params.clone().as_mut_ptr(),
params.len() as libc::c_uint,
flags as libc::c_uint,
)
};
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { Domain::from_ptr(ptr) })
}
pub fn migrate_to_uri(
&self,
duri: &str,
flags: u32,
dname: Option<&str>,
bandwidth: u64,
) -> Result<(), Error> {
let duri_buf = CString::new(duri).unwrap();
let dname_buf = some_string_to_cstring!(dname);
let ret = unsafe {
sys::virDomainMigrateToURI(
self.as_ptr(),
duri_buf.as_ptr(),
flags as libc::c_ulong,
some_cstring_to_c_chars!(dname_buf),
bandwidth as libc::c_ulong,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(())
}
pub fn migrate_to_uri2(
&self,
dconn_uri: Option<&str>,
mig_uri: Option<&str>,
dxml: Option<&str>,
flags: u32,
dname: Option<&str>,
bandwidth: u64,
) -> Result<(), Error> {
let dconn_uri_buf = some_string_to_cstring!(dconn_uri);
let mig_uri_buf = some_string_to_cstring!(mig_uri);
let dxml_buf = some_string_to_cstring!(dxml);
let dname_buf = some_string_to_cstring!(dname);
let ret = unsafe {
sys::virDomainMigrateToURI2(
self.as_ptr(),
some_cstring_to_c_chars!(dconn_uri_buf),
some_cstring_to_c_chars!(mig_uri_buf),
some_cstring_to_c_chars!(dxml_buf),
flags as libc::c_ulong,
some_cstring_to_c_chars!(dname_buf),
bandwidth as libc::c_ulong,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(())
}
pub fn migrate_to_uri3(
&self,
dconn_uri: Option<&str>,
parameters: MigrateParameters,
flags: u32,
) -> Result<(), Error> {
let params = parameters.to_vec();
let dconn_uri_buf = some_string_to_cstring!(dconn_uri);
let ret = unsafe {
sys::virDomainMigrateToURI3(
self.as_ptr(),
some_cstring_to_c_chars!(dconn_uri_buf),
params.clone().as_mut_ptr(),
params.len() as libc::c_uint,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(())
}
pub fn get_numa_parameters(&self, flags: u32) -> Result<NUMAParameters, Error> {
let mut nparams: libc::c_int = 0;
let ret = unsafe {
sys::virDomainGetNumaParameters(
self.as_ptr(),
ptr::null_mut(),
&mut nparams,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
let mut params: Vec<sys::virTypedParameter> = Vec::with_capacity(nparams as usize);
let ret = unsafe {
sys::virDomainGetNumaParameters(
self.as_ptr(),
params.as_mut_ptr(),
&mut nparams,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
unsafe { params.set_len(nparams as usize) };
let nparams = NUMAParameters::from_vec(params.clone());
unsafe { typed_params_release_c_chars!(params) };
Ok(nparams)
}
pub fn set_numa_parameters(&self, params: NUMAParameters, flags: u32) -> Result<u32, Error> {
let mut cparams = params.to_vec();
let ret = unsafe {
sys::virDomainSetNumaParameters(
self.as_ptr(),
cparams.as_mut_ptr(),
cparams.len() as libc::c_int,
flags as libc::c_uint,
)
};
unsafe { typed_params_release_c_chars!(cparams) };
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
pub fn list_all_snapshots(&self, flags: u32) -> Result<Vec<DomainSnapshot>, Error> {
let mut snaps: *mut sys::virDomainSnapshotPtr = ptr::null_mut();
let size = unsafe {
sys::virDomainListAllSnapshots(self.as_ptr(), &mut snaps, flags as libc::c_uint)
};
if size == -1 {
return Err(Error::last_error());
}
let mut array: Vec<DomainSnapshot> = Vec::new();
for x in 0..size as isize {
array.push(unsafe { DomainSnapshot::from_ptr(*snaps.offset(x)) });
}
unsafe { libc::free(snaps as *mut libc::c_void) };
Ok(array)
}
pub fn get_scheduler_type(&self) -> Result<(String, i32), Error> {
let mut nparams: libc::c_int = -1;
let sched_type = unsafe { sys::virDomainGetSchedulerType(self.as_ptr(), &mut nparams) };
if sched_type.is_null() {
return Err(Error::last_error());
}
Ok((unsafe { c_chars_to_string!(sched_type) }, nparams))
}
pub fn get_scheduler_parameters(&self) -> Result<SchedulerInfo, Error> {
let (sched_type, mut nparams) = self.get_scheduler_type()?;
let mut params: Vec<sys::virTypedParameter> = Vec::with_capacity(nparams as usize);
let ret = unsafe {
sys::virDomainGetSchedulerParameters(self.as_ptr(), params.as_mut_ptr(), &mut nparams)
};
if ret == -1 {
return Err(Error::last_error());
}
unsafe { params.set_len(nparams as usize) };
Ok(SchedulerInfo::from_vec(params, sched_type))
}
pub fn get_scheduler_parameters_flags(
&self,
flags: sys::virDomainModificationImpact,
) -> Result<SchedulerInfo, Error> {
let (sched_type, mut nparams) = self.get_scheduler_type()?;
let mut params: Vec<sys::virTypedParameter> = Vec::with_capacity(nparams as usize);
let ret = unsafe {
sys::virDomainGetSchedulerParametersFlags(
self.as_ptr(),
params.as_mut_ptr(),
&mut nparams,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
unsafe { params.set_len(nparams as usize) };
Ok(SchedulerInfo::from_vec(params, sched_type))
}
pub fn set_scheduler_parameters(&self, sched_info: &SchedulerInfo) -> Result<i32, Error> {
let mut params = sched_info.to_vec();
let ret = unsafe {
sys::virDomainSetSchedulerParameters(
self.as_ptr(),
params.as_mut_ptr(),
params.len() as libc::c_int,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret)
}
pub fn set_scheduler_parameters_flags(
&self,
sched_info: &SchedulerInfo,
flags: sys::virDomainModificationImpact,
) -> Result<i32, Error> {
let mut params = sched_info.to_vec();
let ret = unsafe {
sys::virDomainSetSchedulerParametersFlags(
self.as_ptr(),
params.as_mut_ptr(),
params.len() as libc::c_int,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret)
}
pub fn send_key(
&self,
codeset: sys::virKeycodeSet,
holdtime: u32,
keycodes: *mut u32,
nkeycodes: i32,
flags: u32,
) -> Result<(), Error> {
let ret = unsafe {
sys::virDomainSendKey(
self.as_ptr(),
codeset as libc::c_uint,
holdtime as libc::c_uint,
keycodes as *mut libc::c_uint,
nkeycodes as libc::c_int,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(())
}
pub fn screenshot(&self, stream: &Stream, screen: u32, flags: u32) -> Result<String, Error> {
let n = unsafe {
sys::virDomainScreenshot(
self.as_ptr(),
stream.as_ptr(),
screen as libc::c_uint,
flags as libc::c_uint,
)
};
if n.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { c_chars_to_string!(n) })
}
#[cfg(feature = "qemu")]
pub fn qemu_monitor_command(&self, cmd: &str, flags: u32) -> Result<String, Error> {
let mut result: *mut libc::c_char = std::ptr::null_mut();
let cmd_buf = CString::new(cmd).unwrap();
let ret = unsafe {
sys::virDomainQemuMonitorCommand(
self.as_ptr(),
cmd_buf.as_ptr(),
&mut result,
flags as libc::c_uint,
)
};
if ret == -1 {
return Err(Error::last_error());
}
Ok(unsafe { c_chars_to_string!(result) })
}
#[cfg(feature = "qemu")]
pub fn qemu_agent_command(&self, cmd: &str, timeout: i32, flags: u32) -> Result<String, Error> {
let cmd_buf = CString::new(cmd).unwrap();
let ret = unsafe {
sys::virDomainQemuAgentCommand(
self.as_ptr(),
cmd_buf.as_ptr(),
timeout as libc::c_int,
flags as libc::c_uint,
)
};
if ret.is_null() {
return Err(Error::last_error());
}
Ok(unsafe { c_chars_to_string!(ret) })
}
}