feature(krata): dynamic resource allocation (closes #298) (#333)

This commit is contained in:
Alex Zenla
2024-08-14 01:14:49 -07:00
committed by GitHub
parent 1dca770091
commit 87530edf70
15 changed files with 251 additions and 31 deletions

View File

@ -6,6 +6,7 @@ use crate::{
};
use async_stream::try_stream;
use futures::Stream;
use krata::v1::common::ZoneResourceStatus;
use krata::v1::control::{
GetZoneReply, GetZoneRequest, SetHostPowerManagementPolicyReply,
SetHostPowerManagementPolicyRequest,
@ -25,8 +26,8 @@ use krata::{
HostCpuTopologyInfo, HostStatusReply, HostStatusRequest, ListDevicesReply,
ListDevicesRequest, ListZonesReply, ListZonesRequest, PullImageReply, PullImageRequest,
ReadZoneMetricsReply, ReadZoneMetricsRequest, ResolveZoneIdReply, ResolveZoneIdRequest,
SnoopIdmReply, SnoopIdmRequest, WatchEventsReply, WatchEventsRequest, ZoneConsoleReply,
ZoneConsoleRequest,
SnoopIdmReply, SnoopIdmRequest, UpdateZoneResourcesReply, UpdateZoneResourcesRequest,
WatchEventsReply, WatchEventsRequest, ZoneConsoleReply, ZoneConsoleRequest,
},
},
};
@ -165,6 +166,7 @@ impl ControlService for DaemonControlService {
network_status: None,
exit_status: None,
error_status: None,
resource_status: None,
host: self.glt.host_uuid().to_string(),
domid: u32::MAX,
}),
@ -623,4 +625,67 @@ impl ControlService for DaemonControlService {
zone: zone.cloned(),
}))
}
async fn update_zone_resources(
&self,
request: Request<UpdateZoneResourcesRequest>,
) -> Result<Response<UpdateZoneResourcesReply>, Status> {
let request = request.into_inner();
let uuid = Uuid::from_str(&request.zone_id).map_err(|error| ApiError {
message: error.to_string(),
})?;
let Some(mut zone) = self.zones.read(uuid).await.map_err(ApiError::from)? else {
return Err(ApiError {
message: "zone not found".to_string(),
}
.into());
};
let Some(ref mut status) = zone.status else {
return Err(ApiError {
message: "zone state not available".to_string(),
}
.into());
};
if status.state() != ZoneState::Created {
return Err(ApiError {
message: "zone is in an invalid state".to_string(),
}
.into());
}
if status.domid == 0 || status.domid == u32::MAX {
return Err(ApiError {
message: "zone domid is invalid".to_string(),
}
.into());
}
let resources = request.resources.unwrap_or_default();
self.runtime
.set_max_memory(status.domid, resources.max_memory * 1024 * 1024)
.await
.map_err(|error| ApiError {
message: format!("failed to set maximum memory: {}", error),
})?;
self.runtime
.set_target_memory(status.domid, resources.target_memory * 1024 * 1024)
.await
.map_err(|error| ApiError {
message: format!("failed to set target memory: {}", error),
})?;
status.resource_status = Some(ZoneResourceStatus {
active_resources: Some(resources),
});
self.zones
.update(uuid, zone)
.await
.map_err(ApiError::from)?;
Ok(Response::new(UpdateZoneResourcesReply {}))
}
}

View File

@ -137,6 +137,7 @@ impl DaemonEventGenerator {
network_status: zone.status.clone().unwrap_or_default().network_status,
exit_status: Some(ZoneExitStatus { code }),
error_status: None,
resource_status: zone.status.clone().unwrap_or_default().resource_status,
host: zone.status.clone().map(|x| x.host).unwrap_or_default(),
domid: zone.status.clone().map(|x| x.domid).unwrap_or(u32::MAX),
});

View File

@ -1,8 +1,8 @@
use anyhow::{anyhow, Result};
use futures::StreamExt;
use krata::launchcfg::LaunchPackedFormat;
use krata::v1::common::ZoneOciImageSpec;
use krata::v1::common::{OciImageFormat, Zone, ZoneState, ZoneStatus};
use krata::v1::common::{ZoneOciImageSpec, ZoneResourceStatus};
use krataoci::packer::{service::OciPackerService, OciPackedFormat};
use kratart::launch::{PciBdf, PciDevice, PciRdmReservePolicy, ZoneLaunchNetwork};
use kratart::{launch::ZoneLaunchRequest, Runtime};
@ -176,6 +176,7 @@ impl ZoneCreator<'_> {
let reservation = self.ip_assignment.assign(uuid).await?;
let initial_resources = spec.initial_resources.unwrap_or_default();
let info = self
.runtime
.launch(ZoneLaunchRequest {
@ -189,8 +190,9 @@ impl ZoneCreator<'_> {
image,
kernel,
initrd,
vcpus: spec.cpus,
mem: spec.mem,
cpus: initial_resources.cpus,
max_memory: initial_resources.max_memory,
target_memory: initial_resources.target_memory,
pcis,
env: task
.environment
@ -219,6 +221,9 @@ impl ZoneCreator<'_> {
network_status: Some(ip_reservation_to_network_status(&reservation)),
exit_status: None,
error_status: None,
resource_status: Some(ZoneResourceStatus {
active_resources: Some(initial_resources),
}),
host: self.zlt.host_uuid().to_string(),
domid: info.domid,
});

View File

@ -328,6 +328,7 @@ impl ZoneReconciler {
network_status: None,
exit_status: None,
error_status: None,
resource_status: None,
host: self.zlt.host_uuid().to_string(),
domid: domid.unwrap_or(u32::MAX),
});