use std::{collections::BTreeSet, future::Future, pin::Pin, sync::Arc};
use dotcore_domain::ExecutionPlatform;
#[derive(Clone)]
pub struct RuntimeCapabilityProbes {
pub docker: Arc<dyn DockerCapabilityProbe>,
pub native: Arc<dyn NativeCapabilityProbe>,
}
pub trait DockerCapabilityProbe: Send + Sync {
fn probe(
&self,
) -> Pin<Box<dyn Future<Output = anyhow::Result<DockerCapabilityReport>> + Send + '_>>;
fn nvidia_cdi_selectors(
&self,
) -> Pin<Box<dyn Future<Output = anyhow::Result<BTreeSet<String>>> + Send + '_>>;
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DockerCapabilityReport {
execution_platform: ExecutionPlatform,
cdi_spec_dirs: Vec<String>,
}
impl DockerCapabilityReport {
pub fn new(
execution_platform: ExecutionPlatform,
cdi_spec_dirs: impl IntoIterator<Item = impl Into<String>>,
) -> Self {
Self {
execution_platform,
cdi_spec_dirs: cdi_spec_dirs.into_iter().map(Into::into).collect(),
}
}
pub fn execution_platform(&self) -> &ExecutionPlatform {
&self.execution_platform
}
pub fn cdi_enabled(&self) -> bool {
!self.cdi_spec_dirs.is_empty()
}
pub fn cdi_spec_dirs(&self) -> &[String] {
&self.cdi_spec_dirs
}
}
pub trait NativeCapabilityProbe: Send + Sync {
fn probe(&self) -> NativeCapabilityReport;
}
#[derive(Debug)]
pub struct NativeCapabilityReport {
pub host_platform: Option<ExecutionPlatform>,
pub launcher: Result<(), String>,
pub state_root: Result<(), String>,
pub nix: Result<(), String>,
}
impl NativeCapabilityReport {
pub fn qualify(&self, required: &ExecutionPlatform) -> Result<(), NativeCapabilityFailure> {
if self.host_platform.as_ref() != Some(required) {
let host = self
.host_platform
.as_ref()
.map_or_else(|| "an unsupported platform".to_owned(), ToString::to_string);
return Err(NativeCapabilityFailure {
code: "PLATFORM_UNSUPPORTED",
platform_mismatch: true,
message: format!(
"Native workloads run on this node's {host} platform, but the execution target requires {required}."
),
});
}
for (code, result, subject) in [
(
"LAUNCHER_UNAVAILABLE",
&self.launcher,
"The native launcher",
),
(
"STATE_ROOT_UNWRITABLE",
&self.state_root,
"The native workload state directory",
),
("NIX_UNAVAILABLE", &self.nix, "Nix"),
] {
if let Err(detail) = result {
return Err(NativeCapabilityFailure {
code,
platform_mismatch: false,
message: format!("{subject} is unavailable on this node: {detail}."),
});
}
}
Ok(())
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct NativeCapabilityFailure {
pub code: &'static str,
pub platform_mismatch: bool,
pub message: String,
}