mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-02 21:00:55 +00:00
feature(zone): kernel command line control on launch
This commit is contained in:
parent
1123a1a50a
commit
5dbdbfdee1
3
.github/workflows/check.yml
vendored
3
.github/workflows/check.yml
vendored
@ -26,9 +26,8 @@ jobs:
|
||||
rustup component add rustfmt
|
||||
- name: install linux dependencies
|
||||
run: ./hack/ci/install-linux-deps.sh
|
||||
# Temporarily ignored: https://github.com/edera-dev/krata/issues/206
|
||||
- name: cargo fmt
|
||||
run: ./hack/build/cargo.sh fmt --all -- --check || true
|
||||
run: ./hack/build/cargo.sh fmt --all -- --check
|
||||
shellcheck:
|
||||
name: shellcheck
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -7,9 +7,8 @@ use krata::v1::control::{
|
||||
use tonic::{transport::Channel, Request};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(about = "Display hypervisor diagnostic messages")]
|
||||
pub struct HostHvConsoleCommand {
|
||||
}
|
||||
#[command(about = "Display hypervisor console output")]
|
||||
pub struct HostHvConsoleCommand {}
|
||||
|
||||
impl HostHvConsoleCommand {
|
||||
pub async fn run(self, mut client: ControlServiceClient<Channel>) -> Result<()> {
|
||||
|
@ -6,14 +6,14 @@ use krata::events::EventStream;
|
||||
use krata::v1::control::control_service_client::ControlServiceClient;
|
||||
|
||||
use crate::cli::host::cpu_topology::HostCpuTopologyCommand;
|
||||
use crate::cli::host::hv_console::HostHvConsoleCommand;
|
||||
use crate::cli::host::identify::HostStatusCommand;
|
||||
use crate::cli::host::idm_snoop::HostIdmSnoopCommand;
|
||||
use crate::cli::host::hv_console::HostHvConsoleCommand;
|
||||
|
||||
pub mod cpu_topology;
|
||||
pub mod hv_console;
|
||||
pub mod identify;
|
||||
pub mod idm_snoop;
|
||||
pub mod hv_console;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(about = "Manage the host of the isolation engine")]
|
||||
|
@ -31,6 +31,7 @@ pub struct ControlCommand {
|
||||
command: ControlCommands,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Parser)]
|
||||
pub enum ControlCommands {
|
||||
Zone(ZoneCommand),
|
||||
@ -48,7 +49,11 @@ impl ControlCommand {
|
||||
}
|
||||
|
||||
impl ControlCommands {
|
||||
pub async fn run(self, client: ControlServiceClient<Channel>, events: EventStream) -> Result<()> {
|
||||
pub async fn run(
|
||||
self,
|
||||
client: ControlServiceClient<Channel>,
|
||||
events: EventStream,
|
||||
) -> Result<()> {
|
||||
match self {
|
||||
ControlCommands::Zone(zone) => zone.run(client, events).await,
|
||||
|
||||
|
@ -6,8 +6,8 @@ use krata::{
|
||||
events::EventStream,
|
||||
v1::{
|
||||
common::{
|
||||
zone_image_spec::Image, OciImageFormat, ZoneImageSpec, ZoneOciImageSpec,
|
||||
ZoneResourceSpec, ZoneSpec, ZoneSpecDevice, ZoneState, ZoneTaskSpec,
|
||||
zone_image_spec::Image, OciImageFormat, ZoneImageSpec, ZoneKernelOptionsSpec,
|
||||
ZoneOciImageSpec, ZoneResourceSpec, ZoneSpec, ZoneSpecDevice, ZoneState, ZoneTaskSpec,
|
||||
ZoneTaskSpecEnvVar,
|
||||
},
|
||||
control::{
|
||||
@ -91,6 +91,10 @@ pub struct ZoneLaunchCommand {
|
||||
initrd: Option<String>,
|
||||
#[arg(short = 'w', long, help = "Working directory")]
|
||||
working_directory: Option<String>,
|
||||
#[arg(long, help = "Enable verbose logging on the kernel")]
|
||||
kernel_verbose: bool,
|
||||
#[arg(long, help = "Additional kernel cmdline options")]
|
||||
kernel_cmdline_append: Option<String>,
|
||||
#[arg(help = "Container image for zone to use")]
|
||||
oci: String,
|
||||
#[arg(
|
||||
@ -166,6 +170,10 @@ impl ZoneLaunchCommand {
|
||||
.iter()
|
||||
.map(|name| ZoneSpecDevice { name: name.clone() })
|
||||
.collect(),
|
||||
kernel_options: Some(ZoneKernelOptionsSpec {
|
||||
verbose: self.kernel_verbose,
|
||||
cmdline_append: self.kernel_cmdline_append.clone().unwrap_or_default(),
|
||||
}),
|
||||
}),
|
||||
};
|
||||
let response = client
|
||||
|
@ -26,7 +26,7 @@ pub mod logs;
|
||||
pub mod metrics;
|
||||
pub mod resolve;
|
||||
pub mod top;
|
||||
mod update_resources;
|
||||
pub mod update_resources;
|
||||
pub mod watch;
|
||||
|
||||
#[derive(Parser)]
|
||||
@ -46,6 +46,7 @@ impl ZoneCommand {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Subcommand)]
|
||||
pub enum ZoneCommands {
|
||||
Attach(ZoneAttachCommand),
|
||||
|
@ -25,10 +25,10 @@ use krata::{
|
||||
ExecInsideZoneRequest, GetHostCpuTopologyReply, GetHostCpuTopologyRequest,
|
||||
HostCpuTopologyInfo, HostStatusReply, HostStatusRequest, ListDevicesReply,
|
||||
ListDevicesRequest, ListZonesReply, ListZonesRequest, PullImageReply, PullImageRequest,
|
||||
ReadZoneMetricsReply, ReadZoneMetricsRequest, ResolveZoneIdReply, ResolveZoneIdRequest,
|
||||
SnoopIdmReply, SnoopIdmRequest, UpdateZoneResourcesReply, UpdateZoneResourcesRequest,
|
||||
ReadHypervisorConsoleReply, ReadHypervisorConsoleRequest, ReadZoneMetricsReply,
|
||||
ReadZoneMetricsRequest, ResolveZoneIdReply, ResolveZoneIdRequest, SnoopIdmReply,
|
||||
SnoopIdmRequest, UpdateZoneResourcesReply, UpdateZoneResourcesRequest,
|
||||
WatchEventsReply, WatchEventsRequest, ZoneConsoleReply, ZoneConsoleRequest,
|
||||
ReadHypervisorConsoleRequest, ReadHypervisorConsoleReply,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -716,9 +716,15 @@ impl ControlService for DaemonControlService {
|
||||
&self,
|
||||
_request: Request<ReadHypervisorConsoleRequest>,
|
||||
) -> Result<Response<ReadHypervisorConsoleReply>, Status> {
|
||||
let data = self.runtime.read_hypervisor_console(false).await.map_err(|error| ApiError {
|
||||
message: error.to_string(),
|
||||
})?;
|
||||
Ok(Response::new(ReadHypervisorConsoleReply { data: data.to_string() }))
|
||||
let data = self
|
||||
.runtime
|
||||
.read_hypervisor_console(false)
|
||||
.await
|
||||
.map_err(|error| ApiError {
|
||||
message: error.to_string(),
|
||||
})?;
|
||||
Ok(Response::new(ReadHypervisorConsoleReply {
|
||||
data: data.to_string(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -184,10 +184,19 @@ impl ZoneCreator<'_> {
|
||||
initial_resources.max_cpus = initial_resources.target_cpus;
|
||||
}
|
||||
spec.initial_resources = Some(initial_resources);
|
||||
let kernel_options = spec.kernel_options.clone().unwrap_or_default();
|
||||
let info = self
|
||||
.runtime
|
||||
.launch(ZoneLaunchRequest {
|
||||
format: LaunchPackedFormat::Squashfs,
|
||||
format: match image.format {
|
||||
OciPackedFormat::Squashfs => LaunchPackedFormat::Squashfs,
|
||||
OciPackedFormat::Erofs => LaunchPackedFormat::Erofs,
|
||||
_ => {
|
||||
return Err(anyhow!(
|
||||
"oci image is in an invalid format, which isn't compatible with launch"
|
||||
));
|
||||
}
|
||||
},
|
||||
uuid: Some(uuid),
|
||||
name: if spec.name.is_empty() {
|
||||
None
|
||||
@ -208,7 +217,8 @@ impl ZoneCreator<'_> {
|
||||
.map(|x| (x.key.clone(), x.value.clone()))
|
||||
.collect::<HashMap<_, _>>(),
|
||||
run: empty_vec_optional(task.command.clone()),
|
||||
debug: false,
|
||||
kernel_verbose: kernel_options.verbose,
|
||||
kernel_cmdline_append: kernel_options.cmdline_append,
|
||||
addons_image: Some(self.addons_path.to_path_buf()),
|
||||
network: ZoneLaunchNetwork {
|
||||
ipv4: reservation.ipv4.to_string(),
|
||||
|
@ -25,6 +25,7 @@ message ZoneSpec {
|
||||
ZoneTaskSpec task = 6;
|
||||
repeated ZoneSpecAnnotation annotations = 7;
|
||||
repeated ZoneSpecDevice devices = 8;
|
||||
ZoneKernelOptionsSpec kernel_options = 9;
|
||||
}
|
||||
|
||||
message ZoneResourceSpec {
|
||||
@ -40,6 +41,11 @@ message ZoneImageSpec {
|
||||
}
|
||||
}
|
||||
|
||||
message ZoneKernelOptionsSpec {
|
||||
bool verbose = 1;
|
||||
string cmdline_append = 2;
|
||||
}
|
||||
|
||||
enum OciImageFormat {
|
||||
OCI_IMAGE_FORMAT_UNKNOWN = 0;
|
||||
OCI_IMAGE_FORMAT_SQUASHFS = 1;
|
||||
|
@ -37,7 +37,8 @@ pub struct ZoneLaunchRequest {
|
||||
pub env: HashMap<String, String>,
|
||||
pub run: Option<Vec<String>>,
|
||||
pub pcis: Vec<PciDevice>,
|
||||
pub debug: bool,
|
||||
pub kernel_verbose: bool,
|
||||
pub kernel_cmdline_append: String,
|
||||
pub image: OciPackedImage,
|
||||
pub addons_image: Option<PathBuf>,
|
||||
pub network: ZoneLaunchNetwork,
|
||||
@ -139,9 +140,14 @@ impl ZoneLauncher {
|
||||
None
|
||||
};
|
||||
let mut cmdline_options = ["console=hvc0"].to_vec();
|
||||
if !request.debug {
|
||||
if !request.kernel_verbose {
|
||||
cmdline_options.push("quiet");
|
||||
}
|
||||
|
||||
if !request.kernel_cmdline_append.is_empty() {
|
||||
cmdline_options.push(&request.kernel_cmdline_append);
|
||||
}
|
||||
|
||||
let cmdline = cmdline_options.join(" ");
|
||||
|
||||
let zone_mac_string = request.network.zone_mac.to_string().replace('-', ":");
|
||||
|
@ -307,11 +307,13 @@ impl Runtime {
|
||||
}
|
||||
|
||||
pub async fn read_hypervisor_console(&self, clear: bool) -> Result<Arc<str>> {
|
||||
let index = 0 as u32;
|
||||
let (rawbuf, newindex) = self.context
|
||||
.xen
|
||||
.call
|
||||
.read_console_ring_raw(clear, index).await?;
|
||||
let index = 0_u32;
|
||||
let (rawbuf, newindex) = self
|
||||
.context
|
||||
.xen
|
||||
.call
|
||||
.read_console_ring_raw(clear, index)
|
||||
.await?;
|
||||
let buf = std::str::from_utf8(&rawbuf[..newindex as usize])?;
|
||||
Ok(Arc::from(buf))
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ async fn main() -> Result<()> {
|
||||
env_logger::init();
|
||||
|
||||
let call = XenCall::open(0)?;
|
||||
let index = 0 as u32;
|
||||
let index = 0_u32;
|
||||
let (buf, newindex) = call.read_console_ring_raw(false, index).await?;
|
||||
|
||||
match std::str::from_utf8(&buf[..newindex as usize]) {
|
||||
|
@ -26,8 +26,8 @@ use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use sys::{
|
||||
CpuId, E820Entry, ForeignMemoryMap, PhysdevMapPirq, Sysctl, SysctlCputopo, SysctlCputopoinfo,
|
||||
SysctlPhysinfo, SysctlPmOp, SysctlPmOpValue, SysctlSetCpuFreqGov, SysctlValue, SysctlReadconsole,
|
||||
VcpuGuestContextAny, HYPERVISOR_PHYSDEV_OP, HYPERVISOR_SYSCTL, PHYSDEVOP_MAP_PIRQ,
|
||||
SysctlPhysinfo, SysctlPmOp, SysctlPmOpValue, SysctlReadconsole, SysctlSetCpuFreqGov,
|
||||
SysctlValue, VcpuGuestContextAny, HYPERVISOR_PHYSDEV_OP, HYPERVISOR_SYSCTL, PHYSDEVOP_MAP_PIRQ,
|
||||
XEN_DOMCTL_MAX_INTERFACE_VERSION, XEN_DOMCTL_MIN_INTERFACE_VERSION, XEN_MEM_SET_MEMORY_MAP,
|
||||
XEN_SYSCTL_CPUTOPOINFO, XEN_SYSCTL_MAX_INTERFACE_VERSION, XEN_SYSCTL_MIN_INTERFACE_VERSION,
|
||||
XEN_SYSCTL_PHYSINFO, XEN_SYSCTL_PM_OP, XEN_SYSCTL_PM_OP_DISABLE_TURBO,
|
||||
@ -1088,7 +1088,11 @@ impl XenCall {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn read_console_ring_raw(&self, clear: bool, index: u32) -> Result<([u8; 16384], u32)> {
|
||||
pub async fn read_console_ring_raw(
|
||||
&self,
|
||||
clear: bool,
|
||||
index: u32,
|
||||
) -> Result<([u8; 16384], u32)> {
|
||||
let mut u8buf = [0u8; 16384];
|
||||
let mut sysctl = Sysctl {
|
||||
cmd: XEN_SYSCTL_READCONSOLE,
|
||||
@ -1098,7 +1102,7 @@ impl XenCall {
|
||||
clear: clear as u8,
|
||||
incremental: 1,
|
||||
pad: 0,
|
||||
index: index,
|
||||
index,
|
||||
buffer: addr_of_mut!(u8buf) as u64,
|
||||
count: 16384,
|
||||
},
|
||||
@ -1109,9 +1113,7 @@ impl XenCall {
|
||||
// Safety: We are passing a SysctlReadconsole struct as part of the hypercall, and
|
||||
// calling the hypercall is known to not change the underlying value outside changing
|
||||
// the values on some SysctlReadconsole fields.
|
||||
let newindex = unsafe {
|
||||
sysctl.value.console.index
|
||||
};
|
||||
let newindex = unsafe { sysctl.value.console.index };
|
||||
Ok((u8buf, newindex))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user