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()?)
 | 
					        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()
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user