Add REST route to get networks list
This commit is contained in:
parent
f2237d4f2f
commit
2741faa95b
@ -377,3 +377,39 @@ impl Handler<DefineNetwork> for LibVirtActor {
|
|||||||
XMLUuid::parse_from_str(&network.get_uuid_string()?)
|
XMLUuid::parse_from_str(&network.get_uuid_string()?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -21,3 +21,15 @@ pub async fn create(client: LibVirtReq, req: web::Json<NetworkInfo>) -> HttpResu
|
|||||||
|
|
||||||
Ok(HttpResponse::Ok().json(NetworkID { id }))
|
Ok(HttpResponse::Ok().json(NetworkID { id }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the list of networks
|
||||||
|
pub async fn list(client: LibVirtReq) -> HttpResult {
|
||||||
|
let networks = client
|
||||||
|
.get_full_networks_list()
|
||||||
|
.await?
|
||||||
|
.into_iter()
|
||||||
|
.map(|n| NetworkInfo::from_xml(n).unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok().json(networks))
|
||||||
|
}
|
||||||
|
@ -34,7 +34,7 @@ pub async fn create(client: LibVirtReq, req: web::Json<VMInfo>) -> HttpResult {
|
|||||||
|
|
||||||
/// Get the list of domains
|
/// Get the list of domains
|
||||||
pub async fn list_all(client: LibVirtReq) -> HttpResult {
|
pub async fn list_all(client: LibVirtReq) -> HttpResult {
|
||||||
let list = client.get_full_list().await?;
|
let list = client.get_full_domains_list().await?;
|
||||||
let mut out = Vec::with_capacity(list.len());
|
let mut out = Vec::with_capacity(list.len());
|
||||||
|
|
||||||
for entry in list {
|
for entry in list {
|
||||||
|
@ -14,7 +14,7 @@ impl LibVirtClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the full list of domain
|
/// Get the full list of domain
|
||||||
pub async fn get_full_list(&self) -> anyhow::Result<Vec<DomainXML>> {
|
pub async fn get_full_domains_list(&self) -> anyhow::Result<Vec<DomainXML>> {
|
||||||
let ids = self.0.send(libvirt_actor::GetDomainsListReq).await??;
|
let ids = self.0.send(libvirt_actor::GetDomainsListReq).await??;
|
||||||
let mut info = Vec::with_capacity(ids.len());
|
let mut info = Vec::with_capacity(ids.len());
|
||||||
for id in ids {
|
for id in ids {
|
||||||
@ -96,4 +96,19 @@ impl LibVirtClient {
|
|||||||
pub async fn update_network(&self, network: NetworkXML) -> anyhow::Result<XMLUuid> {
|
pub async fn update_network(&self, network: NetworkXML) -> anyhow::Result<XMLUuid> {
|
||||||
self.0.send(libvirt_actor::DefineNetwork(network)).await?
|
self.0.send(libvirt_actor::DefineNetwork(network)).await?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the full list of networks
|
||||||
|
pub async fn get_full_networks_list(&self) -> anyhow::Result<Vec<NetworkXML>> {
|
||||||
|
let ids = self.0.send(libvirt_actor::GetNetworksListReq).await??;
|
||||||
|
let mut info = Vec::with_capacity(ids.len());
|
||||||
|
for id in ids {
|
||||||
|
info.push(self.get_single_network(id).await?)
|
||||||
|
}
|
||||||
|
Ok(info)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the information about a single network
|
||||||
|
pub async fn get_single_network(&self, id: XMLUuid) -> anyhow::Result<NetworkXML> {
|
||||||
|
self.0.send(libvirt_actor::GetNetworkXMLReq(id)).await?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,5 +304,6 @@ pub struct NetworkXML {
|
|||||||
pub dns: Option<NetworkDNSXML>,
|
pub dns: Option<NetworkDNSXML>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub domain: Option<NetworkDomainXML>,
|
pub domain: Option<NetworkDomainXML>,
|
||||||
|
#[serde(default, rename = "ip")]
|
||||||
pub ips: Vec<NetworkIPXML>,
|
pub ips: Vec<NetworkIPXML>,
|
||||||
}
|
}
|
||||||
|
@ -423,6 +423,64 @@ impl NetworkInfo {
|
|||||||
ips,
|
ips,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_xml(xml: NetworkXML) -> anyhow::Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
name: xml.name,
|
||||||
|
uuid: xml.uuid,
|
||||||
|
title: xml.title,
|
||||||
|
description: xml.description,
|
||||||
|
forward_mode: match xml.forward {
|
||||||
|
None => NetworkForwardMode::Isolated,
|
||||||
|
Some(_) => NetworkForwardMode::NAT,
|
||||||
|
},
|
||||||
|
device: xml.forward.map(|f| f.dev).unwrap_or(None),
|
||||||
|
dns_server: xml.dns.map(|d| d.forwarder.addr),
|
||||||
|
domain: xml.domain.map(|d| d.name),
|
||||||
|
ip_v4: xml
|
||||||
|
.ips
|
||||||
|
.iter()
|
||||||
|
.find(|i| i.family != "ipv6")
|
||||||
|
.map(|i| IPV4Config {
|
||||||
|
bridge_address: extract_ipv4(i.address),
|
||||||
|
prefix: i.prefix,
|
||||||
|
dhcp_range: i
|
||||||
|
.dhcp
|
||||||
|
.as_ref()
|
||||||
|
.map(|d| [extract_ipv4(d.range.start), extract_ipv4(d.range.end)]),
|
||||||
|
}),
|
||||||
|
ip_v6: xml
|
||||||
|
.ips
|
||||||
|
.iter()
|
||||||
|
.find(|i| i.family == "ipv6")
|
||||||
|
.map(|i| IPV6Config {
|
||||||
|
bridge_address: extract_ipv6(i.address),
|
||||||
|
prefix: i.prefix,
|
||||||
|
dhcp_range: i
|
||||||
|
.dhcp
|
||||||
|
.as_ref()
|
||||||
|
.map(|d| [extract_ipv6(d.range.start), extract_ipv6(d.range.end)]),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_ipv4(ip: IpAddr) -> Ipv4Addr {
|
||||||
|
match ip {
|
||||||
|
IpAddr::V4(i) => i,
|
||||||
|
IpAddr::V6(_) => {
|
||||||
|
panic!("IPv6 found in IPv4 definition!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_ipv6(ip: IpAddr) -> Ipv6Addr {
|
||||||
|
match ip {
|
||||||
|
IpAddr::V4(_) => {
|
||||||
|
panic!("IPv4 found in IPv6 definition!")
|
||||||
|
}
|
||||||
|
IpAddr::V6(i) => i,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -181,6 +181,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
"/api/network/create",
|
"/api/network/create",
|
||||||
web::post().to(network_controller::create),
|
web::post().to(network_controller::create),
|
||||||
)
|
)
|
||||||
|
.route("/api/network/list", web::get().to(network_controller::list))
|
||||||
})
|
})
|
||||||
.bind(&AppConfig::get().listen_address)?
|
.bind(&AppConfig::get().listen_address)?
|
||||||
.run()
|
.run()
|
||||||
|
Loading…
Reference in New Issue
Block a user