Can define network filters
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
use crate::libvirt_client::LibVirtClient;
|
||||
use actix_http::StatusCode;
|
||||
use actix_web::body::BoxBody;
|
||||
use actix_web::{web, HttpResponse};
|
||||
use std::error::Error;
|
||||
@ -32,8 +33,15 @@ impl Display for HttpErr {
|
||||
}
|
||||
|
||||
impl actix_web::error::ResponseError for HttpErr {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match self {
|
||||
HttpErr::Err(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
HttpErr::HTTPResponse(r) => r.status(),
|
||||
}
|
||||
}
|
||||
fn error_response(&self) -> HttpResponse<BoxBody> {
|
||||
log::error!("Error while processing request! {}", self);
|
||||
|
||||
HttpResponse::InternalServerError().body("Failed to execute request!")
|
||||
}
|
||||
}
|
||||
|
@ -112,10 +112,15 @@ pub async fn update(
|
||||
id: web::Path<SingleVMUUidReq>,
|
||||
req: web::Json<VMInfo>,
|
||||
) -> HttpResult {
|
||||
let mut domain = req.0.as_tomain().map_err(|e| {
|
||||
log::error!("Failed to extract domain info! {e}");
|
||||
HttpResponse::BadRequest().json(format!("Failed to extract domain info! {e}"))
|
||||
})?;
|
||||
let mut domain = match req.0.as_tomain() {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
log::error!("Failed to extract domain info! {e}");
|
||||
return Ok(
|
||||
HttpResponse::BadRequest().json(format!("Failed to extract domain info! {e}"))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
domain.uuid = Some(id.uid);
|
||||
if let Err(e) = client.update_domain(req.0, domain).await {
|
||||
|
@ -63,6 +63,24 @@ pub struct NetIntModelXML {
|
||||
pub r#type: String,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[serde(rename = "filterref")]
|
||||
pub struct NetIntFilterParameterXML {
|
||||
#[serde(rename = "@name")]
|
||||
pub name: String,
|
||||
#[serde(rename = "@value")]
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[serde(rename = "filterref")]
|
||||
pub struct NetIntfilterRefXML {
|
||||
#[serde(rename = "@filter")]
|
||||
pub filter: String,
|
||||
#[serde(rename = "parameter", default)]
|
||||
pub parameters: Vec<NetIntFilterParameterXML>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[serde(rename = "interface")]
|
||||
pub struct DomainNetInterfaceXML {
|
||||
@ -73,6 +91,8 @@ pub struct DomainNetInterfaceXML {
|
||||
pub source: Option<NetIntSourceXML>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub model: Option<NetIntModelXML>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub filterref: Option<NetIntfilterRefXML>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
|
@ -24,11 +24,24 @@ pub enum VMArchitecture {
|
||||
X86_64,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct NWFilterParam {
|
||||
name: String,
|
||||
value: String,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct NWFilterRef {
|
||||
name: String,
|
||||
parameters: Vec<NWFilterParam>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct Network {
|
||||
mac: String,
|
||||
#[serde(flatten)]
|
||||
r#type: NetworkType,
|
||||
mac: String,
|
||||
nwfilterref: Option<NWFilterRef>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
@ -157,6 +170,67 @@ impl VMInfo {
|
||||
false => (None, None),
|
||||
};
|
||||
|
||||
// Process network card
|
||||
let mut networks = vec![];
|
||||
for n in &self.networks {
|
||||
let mac = NetMacAddress {
|
||||
address: n.mac.to_string(),
|
||||
};
|
||||
|
||||
let model = Some(NetIntModelXML {
|
||||
r#type: "virtio".to_string(),
|
||||
});
|
||||
|
||||
let filterref = if let Some(n) = &n.nwfilterref {
|
||||
if !regex!("^[a-zA-Z0-9\\_\\-]+$").is_match(&n.name) {
|
||||
log::error!("Filter ref name {} is invalid", n.name);
|
||||
return Err(StructureExtraction("Network filter ref name is invalid!").into());
|
||||
}
|
||||
|
||||
for p in &n.parameters {
|
||||
if !regex!("^[a-zA-Z0-9_-]+$").is_match(&p.name) {
|
||||
return Err(StructureExtraction(
|
||||
"Network filter ref parameter name is invalid!",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
}
|
||||
|
||||
Some(NetIntfilterRefXML {
|
||||
filter: n.name.to_string(),
|
||||
parameters: n
|
||||
.parameters
|
||||
.iter()
|
||||
.map(|f| NetIntFilterParameterXML {
|
||||
name: f.name.to_string(),
|
||||
value: f.value.to_string(),
|
||||
})
|
||||
.collect(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
networks.push(match &n.r#type {
|
||||
NetworkType::UserspaceSLIRPStack => DomainNetInterfaceXML {
|
||||
mac,
|
||||
r#type: "user".to_string(),
|
||||
source: None,
|
||||
model,
|
||||
filterref,
|
||||
},
|
||||
NetworkType::DefinedNetwork { network } => DomainNetInterfaceXML {
|
||||
mac,
|
||||
r#type: "network".to_string(),
|
||||
source: Some(NetIntSourceXML {
|
||||
network: network.to_string(),
|
||||
}),
|
||||
model,
|
||||
filterref,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Check disks name for duplicates
|
||||
for disk in &self.disks {
|
||||
if self.disks.iter().filter(|d| d.name == disk.name).count() > 1 {
|
||||
@ -164,7 +238,8 @@ impl VMInfo {
|
||||
}
|
||||
}
|
||||
|
||||
// Apply disks configuration
|
||||
// Apply disks configuration. Starting from now, the function should ideally never fail due to
|
||||
// bad user input
|
||||
for disk in &self.disks {
|
||||
disk.check_config()?;
|
||||
disk.apply_config(uuid)?;
|
||||
@ -199,34 +274,6 @@ impl VMInfo {
|
||||
})
|
||||
}
|
||||
|
||||
let mut networks = vec![];
|
||||
for n in &self.networks {
|
||||
networks.push(match &n.r#type {
|
||||
NetworkType::UserspaceSLIRPStack => DomainNetInterfaceXML {
|
||||
mac: NetMacAddress {
|
||||
address: n.mac.to_string(),
|
||||
},
|
||||
r#type: "user".to_string(),
|
||||
source: None,
|
||||
model: Some(NetIntModelXML {
|
||||
r#type: "virtio".to_string(),
|
||||
}),
|
||||
},
|
||||
NetworkType::DefinedNetwork { network } => DomainNetInterfaceXML {
|
||||
mac: NetMacAddress {
|
||||
address: n.mac.to_string(),
|
||||
},
|
||||
r#type: "network".to_string(),
|
||||
source: Some(NetIntSourceXML {
|
||||
network: network.to_string(),
|
||||
}),
|
||||
model: Some(NetIntModelXML {
|
||||
r#type: "virtio".to_string(),
|
||||
}),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
Ok(DomainXML {
|
||||
r#type: "kvm".to_string(),
|
||||
name: self.name.to_string(),
|
||||
@ -376,6 +423,17 @@ impl VMInfo {
|
||||
)));
|
||||
}
|
||||
},
|
||||
nwfilterref: d.filterref.as_ref().map(|f| NWFilterRef {
|
||||
name: f.filter.to_string(),
|
||||
parameters: f
|
||||
.parameters
|
||||
.iter()
|
||||
.map(|p| NWFilterParam {
|
||||
name: p.name.to_string(),
|
||||
value: p.value.to_string(),
|
||||
})
|
||||
.collect(),
|
||||
}),
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
|
Reference in New Issue
Block a user