Add REST route to get networks list
This commit is contained in:
		@@ -377,3 +377,39 @@ impl Handler<DefineNetwork> for LibVirtActor {
 | 
			
		||||
        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 }))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// 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
 | 
			
		||||
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());
 | 
			
		||||
 | 
			
		||||
    for entry in list {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ impl LibVirtClient {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// 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 mut info = Vec::with_capacity(ids.len());
 | 
			
		||||
        for id in ids {
 | 
			
		||||
@@ -96,4 +96,19 @@ impl LibVirtClient {
 | 
			
		||||
    pub async fn update_network(&self, network: NetworkXML) -> anyhow::Result<XMLUuid> {
 | 
			
		||||
        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>,
 | 
			
		||||
    #[serde(skip_serializing_if = "Option::is_none")]
 | 
			
		||||
    pub domain: Option<NetworkDomainXML>,
 | 
			
		||||
    #[serde(default, rename = "ip")]
 | 
			
		||||
    pub ips: Vec<NetworkIPXML>,
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -423,6 +423,64 @@ impl NetworkInfo {
 | 
			
		||||
            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)]
 | 
			
		||||
 
 | 
			
		||||
@@ -181,6 +181,7 @@ async fn main() -> std::io::Result<()> {
 | 
			
		||||
                "/api/network/create",
 | 
			
		||||
                web::post().to(network_controller::create),
 | 
			
		||||
            )
 | 
			
		||||
            .route("/api/network/list", web::get().to(network_controller::list))
 | 
			
		||||
    })
 | 
			
		||||
    .bind(&AppConfig::get().listen_address)?
 | 
			
		||||
    .run()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user