621 lines
20 KiB
Rust
621 lines
20 KiB
Rust
use crate::app_config::AppConfig;
|
|
use crate::libvirt_lib_structures::domain::*;
|
|
use crate::libvirt_lib_structures::network::*;
|
|
use crate::libvirt_lib_structures::nwfilter::*;
|
|
use crate::libvirt_lib_structures::*;
|
|
use crate::libvirt_rest_structures::hypervisor::*;
|
|
use crate::libvirt_rest_structures::net::*;
|
|
use crate::libvirt_rest_structures::nw_filter::NetworkFilter;
|
|
use crate::libvirt_rest_structures::vm::*;
|
|
use actix::{Actor, Context, Handler, Message};
|
|
use image::ImageOutputFormat;
|
|
use std::io::Cursor;
|
|
use virt::connect::Connect;
|
|
use virt::domain::Domain;
|
|
use virt::network::Network;
|
|
use virt::nwfilter::NWFilter;
|
|
use virt::stream::Stream;
|
|
use virt::sys;
|
|
use virt::sys::VIR_DOMAIN_XML_SECURE;
|
|
|
|
pub struct LibVirtActor {
|
|
m: Connect,
|
|
}
|
|
|
|
impl LibVirtActor {
|
|
/// Connect to hypervisor
|
|
pub async fn connect() -> anyhow::Result<Self> {
|
|
let hypervisor_uri = AppConfig::get().hypervisor_uri.as_deref().unwrap_or("");
|
|
log::info!(
|
|
"Will connect to hypvervisor at address '{}'",
|
|
hypervisor_uri
|
|
);
|
|
let conn = Connect::open(hypervisor_uri)?;
|
|
|
|
Ok(Self { m: conn })
|
|
}
|
|
}
|
|
|
|
impl Actor for LibVirtActor {
|
|
type Context = Context<Self>;
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<HypervisorInfo>")]
|
|
pub struct GetHypervisorInfo;
|
|
|
|
impl Handler<GetHypervisorInfo> for LibVirtActor {
|
|
type Result = anyhow::Result<HypervisorInfo>;
|
|
|
|
fn handle(&mut self, _msg: GetHypervisorInfo, _ctx: &mut Self::Context) -> Self::Result {
|
|
let node = self.m.get_node_info()?;
|
|
Ok(HypervisorInfo {
|
|
r#type: self.m.get_type()?,
|
|
hyp_version: self.m.get_hyp_version()?,
|
|
lib_version: self.m.get_lib_version()?,
|
|
capabilities: self.m.get_capabilities()?,
|
|
free_memory: self.m.get_free_memory()?,
|
|
hostname: self.m.get_hostname()?,
|
|
node: HypervisorNodeInfo {
|
|
cpu_model: node.model,
|
|
memory_size: node.memory,
|
|
number_of_active_cpus: node.cpus,
|
|
cpu_frequency_mhz: node.mhz,
|
|
number_of_numa_cell: node.nodes,
|
|
number_of_cpu_socket_per_node: node.sockets,
|
|
number_of_core_per_sockets: node.cores,
|
|
number_of_threads_per_core: node.threads,
|
|
},
|
|
})
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<Vec<XMLUuid>>")]
|
|
pub struct GetDomainsListReq;
|
|
|
|
impl Handler<GetDomainsListReq> for LibVirtActor {
|
|
type Result = anyhow::Result<Vec<XMLUuid>>;
|
|
|
|
fn handle(&mut self, _msg: GetDomainsListReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Get full list of domains");
|
|
let domains = self.m.list_all_domains(0)?;
|
|
let mut ids = Vec::with_capacity(domains.len());
|
|
|
|
for d in domains {
|
|
ids.push(XMLUuid::parse_from_str(&d.get_uuid_string()?)?);
|
|
}
|
|
|
|
Ok(ids)
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<DomainXML>")]
|
|
pub struct GetDomainXMLReq(pub XMLUuid);
|
|
|
|
impl Handler<GetDomainXMLReq> for LibVirtActor {
|
|
type Result = anyhow::Result<DomainXML>;
|
|
|
|
fn handle(&mut self, msg: GetDomainXMLReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Get domain XML:\n{}", msg.0.as_string());
|
|
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
let xml = domain.get_xml_desc(VIR_DOMAIN_XML_SECURE)?;
|
|
log::debug!("XML = {}", xml);
|
|
Ok(serde_xml_rs::from_str(&xml)?)
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<String>")]
|
|
pub struct GetSourceDomainXMLReq(pub XMLUuid);
|
|
|
|
impl Handler<GetSourceDomainXMLReq> for LibVirtActor {
|
|
type Result = anyhow::Result<String>;
|
|
|
|
fn handle(&mut self, msg: GetSourceDomainXMLReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Get domain source XML:\n{}", msg.0.as_string());
|
|
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
Ok(domain.get_xml_desc(VIR_DOMAIN_XML_SECURE)?)
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<XMLUuid>")]
|
|
pub struct DefineDomainReq(pub VMInfo, pub DomainXML);
|
|
|
|
impl Handler<DefineDomainReq> for LibVirtActor {
|
|
type Result = anyhow::Result<XMLUuid>;
|
|
|
|
fn handle(&mut self, mut msg: DefineDomainReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
let xml = msg.1.into_xml()?;
|
|
|
|
log::debug!("Define domain:\n{}", xml);
|
|
let domain = Domain::define_xml(&self.m, &xml)?;
|
|
let uuid = XMLUuid::parse_from_str(&domain.get_uuid_string()?)?;
|
|
|
|
// Save a copy of the source definition
|
|
msg.0.uuid = Some(uuid);
|
|
let json = serde_json::to_string(&msg.0)?;
|
|
std::fs::write(AppConfig::get().vm_definition_path(&msg.0.name), json)?;
|
|
|
|
Ok(uuid)
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<()>")]
|
|
pub struct DeleteDomainReq {
|
|
pub id: XMLUuid,
|
|
pub keep_files: bool,
|
|
}
|
|
|
|
impl Handler<DeleteDomainReq> for LibVirtActor {
|
|
type Result = anyhow::Result<()>;
|
|
|
|
fn handle(&mut self, msg: DeleteDomainReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!(
|
|
"Delete domain: {:?} (keep files: {})",
|
|
msg.id,
|
|
msg.keep_files
|
|
);
|
|
|
|
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.id.as_string())?;
|
|
let domain_name = domain.get_name()?;
|
|
|
|
// Remove VNC socket
|
|
let vnc_socket = AppConfig::get().vnc_socket_for_domain(&domain_name);
|
|
if vnc_socket.exists() {
|
|
std::fs::remove_file(vnc_socket)?;
|
|
}
|
|
|
|
// Remove backup definition
|
|
let backup_definition = AppConfig::get().vm_definition_path(&domain_name);
|
|
if backup_definition.exists() {
|
|
std::fs::remove_file(backup_definition)?;
|
|
}
|
|
|
|
// Delete the domain
|
|
domain.undefine_flags(match msg.keep_files {
|
|
true => sys::VIR_DOMAIN_UNDEFINE_KEEP_NVRAM,
|
|
false => sys::VIR_DOMAIN_UNDEFINE_NVRAM,
|
|
})?;
|
|
|
|
if !msg.keep_files {
|
|
log::info!("Delete storage associated with the domain");
|
|
let path = AppConfig::get().vm_storage_path(msg.id);
|
|
if path.exists() {
|
|
std::fs::remove_dir_all(path)?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<DomainState>")]
|
|
pub struct GetDomainStateReq(pub XMLUuid);
|
|
|
|
impl Handler<GetDomainStateReq> for LibVirtActor {
|
|
type Result = anyhow::Result<DomainState>;
|
|
|
|
fn handle(&mut self, msg: GetDomainStateReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Get domain state: {}", msg.0.as_string());
|
|
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
let (state, _) = domain.get_state()?;
|
|
Ok(match state {
|
|
sys::VIR_DOMAIN_NOSTATE => DomainState::NoState,
|
|
sys::VIR_DOMAIN_RUNNING => DomainState::Running,
|
|
sys::VIR_DOMAIN_BLOCKED => DomainState::Blocked,
|
|
sys::VIR_DOMAIN_PAUSED => DomainState::Paused,
|
|
sys::VIR_DOMAIN_SHUTDOWN => DomainState::Shutdown,
|
|
sys::VIR_DOMAIN_SHUTOFF => DomainState::Shutoff,
|
|
sys::VIR_DOMAIN_CRASHED => DomainState::Crashed,
|
|
sys::VIR_DOMAIN_PMSUSPENDED => DomainState::PowerManagementSuspended,
|
|
|
|
_ => DomainState::Other,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<()>")]
|
|
pub struct StartDomainReq(pub XMLUuid);
|
|
|
|
impl Handler<StartDomainReq> for LibVirtActor {
|
|
type Result = anyhow::Result<()>;
|
|
|
|
fn handle(&mut self, msg: StartDomainReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Start domain: {}", msg.0.as_string());
|
|
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
domain.create()?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<()>")]
|
|
pub struct ShutdownDomainReq(pub XMLUuid);
|
|
|
|
impl Handler<ShutdownDomainReq> for LibVirtActor {
|
|
type Result = anyhow::Result<()>;
|
|
|
|
fn handle(&mut self, msg: ShutdownDomainReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Shutdown domain: {}", msg.0.as_string());
|
|
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
domain.shutdown()?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<()>")]
|
|
pub struct KillDomainReq(pub XMLUuid);
|
|
|
|
impl Handler<KillDomainReq> for LibVirtActor {
|
|
type Result = anyhow::Result<()>;
|
|
|
|
fn handle(&mut self, msg: KillDomainReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Kill domain: {}", msg.0.as_string());
|
|
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
domain.destroy()?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<()>")]
|
|
pub struct ResetDomainReq(pub XMLUuid);
|
|
|
|
impl Handler<ResetDomainReq> for LibVirtActor {
|
|
type Result = anyhow::Result<()>;
|
|
|
|
fn handle(&mut self, msg: ResetDomainReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Reset domain: {}", msg.0.as_string());
|
|
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
domain.reset()?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<()>")]
|
|
pub struct SuspendDomainReq(pub XMLUuid);
|
|
|
|
impl Handler<SuspendDomainReq> for LibVirtActor {
|
|
type Result = anyhow::Result<()>;
|
|
|
|
fn handle(&mut self, msg: SuspendDomainReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Suspend domain: {}", msg.0.as_string());
|
|
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
domain.suspend()?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<()>")]
|
|
pub struct ResumeDomainReq(pub XMLUuid);
|
|
|
|
impl Handler<ResumeDomainReq> for LibVirtActor {
|
|
type Result = anyhow::Result<()>;
|
|
|
|
fn handle(&mut self, msg: ResumeDomainReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Resume domain: {}", msg.0.as_string());
|
|
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
domain.resume()?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<Vec<u8>>")]
|
|
pub struct ScreenshotDomainReq(pub XMLUuid);
|
|
|
|
impl Handler<ScreenshotDomainReq> for LibVirtActor {
|
|
type Result = anyhow::Result<Vec<u8>>;
|
|
|
|
fn handle(&mut self, msg: ScreenshotDomainReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Take screenshot of domain: {}", msg.0.as_string());
|
|
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
|
|
let stream = Stream::new(&self.m, 0)?;
|
|
domain.screenshot(&stream, 0, 0)?;
|
|
|
|
let mut screen_out = Vec::with_capacity(1000000);
|
|
let mut buff = [0u8; 1000];
|
|
loop {
|
|
let size = stream.recv(&mut buff)?;
|
|
|
|
if size == 0 {
|
|
break;
|
|
}
|
|
screen_out.extend_from_slice(&buff[0..size]);
|
|
}
|
|
|
|
let image = image::load_from_memory(&screen_out)?;
|
|
let mut png_out = Cursor::new(Vec::new());
|
|
image.write_to(&mut png_out, ImageOutputFormat::Png)?;
|
|
|
|
Ok(png_out.into_inner())
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<bool>")]
|
|
pub struct IsDomainAutostart(pub XMLUuid);
|
|
|
|
impl Handler<IsDomainAutostart> for LibVirtActor {
|
|
type Result = anyhow::Result<bool>;
|
|
|
|
fn handle(&mut self, msg: IsDomainAutostart, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!(
|
|
"Check if autostart is enabled for a domain: {}",
|
|
msg.0.as_string()
|
|
);
|
|
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
Ok(domain.get_autostart()?)
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<()>")]
|
|
pub struct SetDomainAutostart(pub XMLUuid, pub bool);
|
|
|
|
impl Handler<SetDomainAutostart> for LibVirtActor {
|
|
type Result = anyhow::Result<()>;
|
|
|
|
fn handle(&mut self, msg: SetDomainAutostart, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!(
|
|
"Set autostart enabled={} for a domain: {}",
|
|
msg.1,
|
|
msg.0.as_string()
|
|
);
|
|
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
domain.set_autostart(msg.1)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<XMLUuid>")]
|
|
pub struct DefineNetwork(pub NetworkInfo, pub NetworkXML);
|
|
|
|
impl Handler<DefineNetwork> for LibVirtActor {
|
|
type Result = anyhow::Result<XMLUuid>;
|
|
|
|
fn handle(&mut self, mut msg: DefineNetwork, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Define network: {:?}", msg.1);
|
|
|
|
log::debug!("Source network structure: {:#?}", msg.1);
|
|
let network_xml = msg.1.into_xml()?;
|
|
log::debug!("Define network XML: {network_xml}");
|
|
|
|
let network = Network::define_xml(&self.m, &network_xml)?;
|
|
let uuid = XMLUuid::parse_from_str(&network.get_uuid_string()?)?;
|
|
|
|
// Save a copy of the source definition
|
|
msg.0.uuid = Some(uuid);
|
|
let json = serde_json::to_string(&msg.0)?;
|
|
std::fs::write(AppConfig::get().net_definition_path(&msg.0.name), json)?;
|
|
|
|
Ok(uuid)
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<Vec<XMLUuid>>")]
|
|
pub struct GetNetworksListReq;
|
|
|
|
impl Handler<GetNetworksListReq> for LibVirtActor {
|
|
type Result = anyhow::Result<Vec<XMLUuid>>;
|
|
|
|
fn handle(&mut self, _msg: GetNetworksListReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Get full list of networks");
|
|
let networks = self.m.list_all_networks(0)?;
|
|
let mut ids = Vec::with_capacity(networks.len());
|
|
|
|
for d in networks {
|
|
ids.push(XMLUuid::parse_from_str(&d.get_uuid_string()?)?);
|
|
}
|
|
|
|
Ok(ids)
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<NetworkXML>")]
|
|
pub struct GetNetworkXMLReq(pub XMLUuid);
|
|
|
|
impl Handler<GetNetworkXMLReq> for LibVirtActor {
|
|
type Result = anyhow::Result<NetworkXML>;
|
|
|
|
fn handle(&mut self, msg: GetNetworkXMLReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Get network XML:\n{}", msg.0.as_string());
|
|
let network = Network::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
let xml = network.get_xml_desc(0)?;
|
|
log::debug!("XML = {}", xml);
|
|
Ok(serde_xml_rs::from_str(&xml)?)
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<String>")]
|
|
pub struct GetSourceNetworkXMLReq(pub XMLUuid);
|
|
|
|
impl Handler<GetSourceNetworkXMLReq> for LibVirtActor {
|
|
type Result = anyhow::Result<String>;
|
|
|
|
fn handle(&mut self, msg: GetSourceNetworkXMLReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Get network XML:\n{}", msg.0.as_string());
|
|
let network = Network::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
Ok(network.get_xml_desc(0)?)
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<()>")]
|
|
pub struct DeleteNetwork(pub XMLUuid);
|
|
|
|
impl Handler<DeleteNetwork> for LibVirtActor {
|
|
type Result = anyhow::Result<()>;
|
|
|
|
fn handle(&mut self, msg: DeleteNetwork, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Delete network: {}\n", msg.0.as_string());
|
|
let network = Network::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
let network_name = network.get_name()?;
|
|
network.undefine()?;
|
|
|
|
// Remove backup definition
|
|
let backup_definition = AppConfig::get().net_definition_path(&network_name);
|
|
if backup_definition.exists() {
|
|
std::fs::remove_file(backup_definition)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<bool>")]
|
|
pub struct IsNetworkAutostart(pub XMLUuid);
|
|
|
|
impl Handler<IsNetworkAutostart> for LibVirtActor {
|
|
type Result = anyhow::Result<bool>;
|
|
|
|
fn handle(&mut self, msg: IsNetworkAutostart, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!(
|
|
"Check if autostart is enabled for a network: {}",
|
|
msg.0.as_string()
|
|
);
|
|
let network = Network::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
Ok(network.get_autostart()?)
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<()>")]
|
|
pub struct SetNetworkAutostart(pub XMLUuid, pub bool);
|
|
|
|
impl Handler<SetNetworkAutostart> for LibVirtActor {
|
|
type Result = anyhow::Result<()>;
|
|
|
|
fn handle(&mut self, msg: SetNetworkAutostart, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!(
|
|
"Set autostart enabled={} for a network: {}",
|
|
msg.1,
|
|
msg.0.as_string()
|
|
);
|
|
let network = Network::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
network.set_autostart(msg.1)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<bool>")]
|
|
pub struct IsNetworkStarted(pub XMLUuid);
|
|
|
|
impl Handler<IsNetworkStarted> for LibVirtActor {
|
|
type Result = anyhow::Result<bool>;
|
|
|
|
fn handle(&mut self, msg: IsNetworkStarted, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Check if a network is started: {}", msg.0.as_string());
|
|
let network = Network::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
Ok(network.is_active()?)
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<()>")]
|
|
pub struct StartNetwork(pub XMLUuid);
|
|
|
|
impl Handler<StartNetwork> for LibVirtActor {
|
|
type Result = anyhow::Result<()>;
|
|
|
|
fn handle(&mut self, msg: StartNetwork, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Start a network: {}", msg.0.as_string());
|
|
let network = Network::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
network.create()?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<()>")]
|
|
pub struct StopNetwork(pub XMLUuid);
|
|
|
|
impl Handler<StopNetwork> for LibVirtActor {
|
|
type Result = anyhow::Result<()>;
|
|
|
|
fn handle(&mut self, msg: StopNetwork, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Stop a network: {}", msg.0.as_string());
|
|
let network = Network::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
network.destroy()?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<Vec<XMLUuid>>")]
|
|
pub struct GetNWFiltersListReq;
|
|
|
|
impl Handler<GetNWFiltersListReq> for LibVirtActor {
|
|
type Result = anyhow::Result<Vec<XMLUuid>>;
|
|
|
|
fn handle(&mut self, _msg: GetNWFiltersListReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Get full list of network filters");
|
|
let networks = self.m.list_all_nw_filters(0)?;
|
|
let mut ids = Vec::with_capacity(networks.len());
|
|
|
|
for d in networks {
|
|
ids.push(XMLUuid::parse_from_str(&d.get_uuid_string()?)?);
|
|
}
|
|
|
|
Ok(ids)
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<NetworkFilterXML>")]
|
|
pub struct GetNWFilterXMLReq(pub XMLUuid);
|
|
|
|
impl Handler<GetNWFilterXMLReq> for LibVirtActor {
|
|
type Result = anyhow::Result<NetworkFilterXML>;
|
|
|
|
fn handle(&mut self, msg: GetNWFilterXMLReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
log::debug!("Get network filter XML:\n{}", msg.0.as_string());
|
|
let filter = NWFilter::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
|
let xml = filter.get_xml_desc(0)?;
|
|
log::debug!("XML = {}", xml);
|
|
NetworkFilterXML::parse_xml(xml)
|
|
}
|
|
}
|
|
|
|
#[derive(Message)]
|
|
#[rtype(result = "anyhow::Result<XMLUuid>")]
|
|
pub struct DefineNWFilterReq(pub NetworkFilter, pub NetworkFilterXML);
|
|
|
|
impl Handler<DefineNWFilterReq> for LibVirtActor {
|
|
type Result = anyhow::Result<XMLUuid>;
|
|
|
|
fn handle(&mut self, mut msg: DefineNWFilterReq, _ctx: &mut Self::Context) -> Self::Result {
|
|
let xml = msg.1.into_xml()?;
|
|
|
|
log::debug!("Define network filter:\n{}", xml);
|
|
let filter = NWFilter::define_xml(&self.m, &xml)?;
|
|
let uuid = XMLUuid::parse_from_str(&filter.get_uuid_string()?)?;
|
|
|
|
// Save a copy of the source definition
|
|
msg.0.uuid = Some(uuid);
|
|
let json = serde_json::to_string(&msg.0)?;
|
|
std::fs::write(
|
|
AppConfig::get().net_filter_definition_path(&msg.0.name),
|
|
json,
|
|
)?;
|
|
|
|
Ok(uuid)
|
|
}
|
|
}
|