From dfb8c965e636fa6b85af45093a9bdc98c3c68b27 Mon Sep 17 00:00:00 2001 From: wllenyj Date: Sun, 24 Oct 2021 03:23:12 +0800 Subject: [PATCH] agent: Separate the ImageService from the AgentService Use a separate ImageService to support PullImage. Fixes #2984 Signed-off-by: wllenyj --- src/agent/protocols/build.rs | 1 + src/agent/protocols/protos/agent.proto | 7 -- src/agent/protocols/protos/image.proto | 31 +++++ src/agent/protocols/src/lib.rs | 2 + src/agent/src/image_rpc.rs | 168 +++++++++++++++++++++++++ src/agent/src/main.rs | 1 + src/agent/src/rpc.rs | 120 +++--------------- src/agent/src/sandbox.rs | 2 + tools/agent-ctl/src/client.rs | 84 +++++++++++-- 9 files changed, 295 insertions(+), 121 deletions(-) create mode 100644 src/agent/protocols/protos/image.proto create mode 100644 src/agent/src/image_rpc.rs diff --git a/src/agent/protocols/build.rs b/src/agent/protocols/build.rs index 4e0aa30522..03fd80b7d3 100644 --- a/src/agent/protocols/build.rs +++ b/src/agent/protocols/build.rs @@ -13,6 +13,7 @@ fn main() { "protos/health.proto", "protos/google/protobuf/empty.proto", "protos/oci.proto", + "protos/image.proto", ]; Codegen::new() diff --git a/src/agent/protocols/protos/agent.proto b/src/agent/protocols/protos/agent.proto index 76b42e0552..c29ef7ebc4 100644 --- a/src/agent/protocols/protos/agent.proto +++ b/src/agent/protocols/protos/agent.proto @@ -67,7 +67,6 @@ service AgentService { rpc CopyFile(CopyFileRequest) returns (google.protobuf.Empty); rpc GetOOMEvent(GetOOMEventRequest) returns (OOMEvent); rpc AddSwap(AddSwapRequest) returns (google.protobuf.Empty); - rpc PullImage(PullImageRequest) returns (google.protobuf.Empty); } message CreateContainerRequest { @@ -514,9 +513,3 @@ message GetMetricsRequest {} message Metrics { string metrics = 1; } - -message PullImageRequest { - string image = 1; - string container_id = 2; - string source_creds = 3; -} diff --git a/src/agent/protocols/protos/image.proto b/src/agent/protocols/protos/image.proto new file mode 100644 index 0000000000..eb62837e68 --- /dev/null +++ b/src/agent/protocols/protos/image.proto @@ -0,0 +1,31 @@ +// +// Copyright (c) 2021 Alibaba Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +syntax = "proto3"; + +option go_package = "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/agent/protocols/grpc"; + +package grpc; + +// Image defines the public APIs for managing images. +service Image { + // PullImage pulls an image with authentication config. + rpc PullImage(PullImageRequest) returns (PullImageResponse) {} +} + +message PullImageRequest { + // Image name (e.g. docker.io/library/busybox:latest). + string image = 1; + // Unique image identifier, used to avoid duplication when unpacking the image layers. + string container_id = 2; + // Use USERNAME[:PASSWORD] for accessing the registry + string source_creds = 3; +} + +message PullImageResponse { + // Reference to the image in use. For most runtimes, this should be an + // image ID or digest. + string image_ref = 1; +} diff --git a/src/agent/protocols/src/lib.rs b/src/agent/protocols/src/lib.rs index 652d541e8f..0fbb67123a 100644 --- a/src/agent/protocols/src/lib.rs +++ b/src/agent/protocols/src/lib.rs @@ -10,5 +10,7 @@ pub mod agent_ttrpc; pub mod empty; pub mod health; pub mod health_ttrpc; +pub mod image; +pub mod image_ttrpc; pub mod oci; pub mod types; diff --git a/src/agent/src/image_rpc.rs b/src/agent/src/image_rpc.rs new file mode 100644 index 0000000000..8fd35f1d7e --- /dev/null +++ b/src/agent/src/image_rpc.rs @@ -0,0 +1,168 @@ +// Copyright (c) 2021 Alibaba Cloud +// +// SPDX-License-Identifier: Apache-2.0 +// + +use std::fs; +use std::path::PathBuf; +use std::process::{Command, ExitStatus}; +use std::sync::Arc; + +use anyhow::{anyhow, ensure, Result}; +use async_trait::async_trait; +use protocols::image; +use tokio::sync::Mutex; +use ttrpc::{self, error::get_rpc_status as ttrpc_error}; + +use crate::rpc::{verify_cid, CONTAINER_BASE}; +use crate::sandbox::Sandbox; + +const SKOPEO_PATH: &str = "/usr/bin/skopeo"; +const UMOCI_PATH: &str = "/usr/local/bin/umoci"; +const IMAGE_OCI: &str = "image_oci:latest"; + +// Convenience macro to obtain the scope logger +macro_rules! sl { + () => { + slog_scope::logger() + }; +} + +pub struct ImageService { + sandbox: Arc>, +} + +impl ImageService { + pub fn new(sandbox: Arc>) -> Self { + Self { sandbox } + } + + fn build_oci_path(cid: &str) -> PathBuf { + let mut oci_path = PathBuf::from("/tmp"); + oci_path.push(cid); + oci_path.push(IMAGE_OCI); + oci_path + } + + fn pull_image_from_registry(image: &str, cid: &str, source_creds: &Option<&str>) -> Result<()> { + let source_image = format!("{}{}", "docker://", image); + + let mut manifest_path = PathBuf::from("/tmp"); + manifest_path.push(cid); + manifest_path.push("image_manifest"); + let target_path_manifest = format!("dir://{}", manifest_path.to_string_lossy()); + + // Define the target transport and path for the OCI image, without signature + let oci_path = Self::build_oci_path(cid); + let target_path_oci = format!("oci://{}", oci_path.to_string_lossy()); + + fs::create_dir_all(&manifest_path)?; + fs::create_dir_all(&oci_path)?; + + info!(sl!(), "Attempting to pull image {}...", &source_image); + + let mut pull_command = Command::new(SKOPEO_PATH); + pull_command + // TODO: need to create a proper policy + .arg("--insecure-policy") + .arg("copy") + .arg(source_image) + .arg(&target_path_manifest); + + if let Some(source_creds) = source_creds { + pull_command.arg("--src-creds").arg(source_creds); + } + + let status: ExitStatus = pull_command.status()?; + ensure!( + status.success(), + "failed to copy image manifest: {:?}", + status, + ); + + // Copy image from one local file-system to another + // Resulting image is still stored in manifest format, but no longer includes the signature + // The image with a signature can then be unpacked into a bundle + let status: ExitStatus = Command::new(SKOPEO_PATH) + .arg("--insecure-policy") + .arg("copy") + .arg(&target_path_manifest) + .arg(&target_path_oci) + .arg("--remove-signatures") + .status()?; + + ensure!(status.success(), "failed to copy image oci: {:?}", status); + + // To save space delete the manifest. + // TODO LATER - when verify image is added, this will need moving the end of that, if required + fs::remove_dir_all(&manifest_path)?; + Ok(()) + } + + fn unpack_image(cid: &str) -> Result<()> { + let source_path_oci = Self::build_oci_path(cid); + let target_path_bundle = format!("{}{}{}", CONTAINER_BASE, "/", cid); + + info!(sl!(), "unpack image"; "cid" => cid, "target_bundle_path" => &target_path_bundle); + + // Unpack image + let status: ExitStatus = Command::new(UMOCI_PATH) + .arg("unpack") + .arg("--image") + .arg(&source_path_oci) + .arg(&target_path_bundle) + .status()?; + + ensure!(status.success(), "failed to unpack image: {:?}", status); + + // To save space delete the oci image after unpack + fs::remove_dir_all(&source_path_oci)?; + + Ok(()) + } + + async fn pull_image(&self, req: &image::PullImageRequest) -> Result { + let image = req.get_image(); + let mut cid = req.get_container_id(); + + if cid.is_empty() { + let v: Vec<&str> = image.rsplit('/').collect(); + if !v[0].is_empty() { + cid = v[0] + } else { + return Err(anyhow!("Invalid image name. {}", image)); + } + } else { + verify_cid(cid)?; + } + + let source_creds = (!req.get_source_creds().is_empty()).then(|| req.get_source_creds()); + + Self::pull_image_from_registry(image, cid, &source_creds)?; + Self::unpack_image(cid)?; + + let mut sandbox = self.sandbox.lock().await; + sandbox.images.insert(String::from(image), cid.to_string()); + Ok(image.to_owned()) + } +} + +#[async_trait] +impl protocols::image_ttrpc::Image for ImageService { + async fn pull_image( + &self, + _ctx: &ttrpc::r#async::TtrpcContext, + req: image::PullImageRequest, + ) -> ttrpc::Result { + match self.pull_image(&req).await { + Ok(r) => { + let mut resp = image::PullImageResponse::new(); + resp.image_ref = r; + return Ok(resp); + } + Err(e) => { + return Err(ttrpc_error(ttrpc::Code::INTERNAL, e.to_string())); + } + } + } +} diff --git a/src/agent/src/main.rs b/src/agent/src/main.rs index c2ae8c7697..b1eb062730 100644 --- a/src/agent/src/main.rs +++ b/src/agent/src/main.rs @@ -73,6 +73,7 @@ use tokio::{ task::JoinHandle, }; +mod image_rpc; mod rpc; mod tracer; diff --git a/src/agent/src/rpc.rs b/src/agent/src/rpc.rs index 0f551d437b..abc41d0c04 100644 --- a/src/agent/src/rpc.rs +++ b/src/agent/src/rpc.rs @@ -11,7 +11,6 @@ use tokio::sync::Mutex; use std::ffi::CString; use std::io; use std::path::Path; -use std::process::ExitStatus; use std::sync::Arc; use ttrpc::{ self, @@ -45,6 +44,7 @@ use nix::unistd::{self, Pid}; use rustjail::process::ProcessOperations; use crate::device::{add_devices, get_virtio_blk_pci_device_name, update_device_cgroup}; +use crate::image_rpc; use crate::linux_abi::*; use crate::metrics::get_metrics; use crate::mount::{add_storages, baremount, remove_mounts, STORAGE_HANDLER_LIST}; @@ -77,10 +77,8 @@ use std::io::{BufRead, BufReader}; use std::os::unix::fs::FileExt; use std::path::PathBuf; -const CONTAINER_BASE: &str = "/run/kata-containers"; +pub const CONTAINER_BASE: &str = "/run/kata-containers"; const MODPROBE_PATH: &str = "/sbin/modprobe"; -const SKOPEO_PATH: &str = "/usr/bin/skopeo"; -const UMOCI_PATH: &str = "/usr/local/bin/umoci"; // Convenience macro to obtain the scope logger macro_rules! sl { @@ -113,7 +111,7 @@ pub struct AgentService { // // ^[a-zA-Z0-9][a-zA-Z0-9_.-]+$ // -fn verify_cid(id: &str) -> Result<()> { +pub fn verify_cid(id: &str) -> Result<()> { let valid = id.len() > 1 && id.chars().next().unwrap().is_alphanumeric() && id @@ -678,22 +676,6 @@ impl protocols::agent_ttrpc::AgentService for AgentService { .map_err(|e| ttrpc_error(ttrpc::Code::INTERNAL, e.to_string())) } - async fn pull_image( - &self, - _ctx: &TtrpcContext, - req: protocols::agent::PullImageRequest, - ) -> ttrpc::Result { - let image = req.get_image(); - let cid = req.get_container_id(); - let source_creds = (!req.get_source_creds().is_empty()).then(|| req.get_source_creds()); - - pull_image_from_registry(image, cid, &source_creds) - .map_err(|e| ttrpc_error(ttrpc::Code::INTERNAL, e.to_string()))?; - unpack_image(cid).map_err(|e| ttrpc_error(ttrpc::Code::INTERNAL, e.to_string()))?; - - Ok(Empty::new()) - } - async fn pause_container( &self, ctx: &TtrpcContext, @@ -1403,7 +1385,7 @@ fn find_process<'a>( } pub fn start(s: Arc>, server_address: &str) -> TtrpcServer { - let agent_service = Box::new(AgentService { sandbox: s }) + let agent_service = Box::new(AgentService { sandbox: s.clone() }) as Box; let agent_worker = Arc::new(agent_service); @@ -1412,15 +1394,21 @@ pub fn start(s: Arc>, server_address: &str) -> TtrpcServer { Box::new(HealthService {}) as Box; let health_worker = Arc::new(health_service); - let aservice = protocols::agent_ttrpc::create_agent_service(agent_worker); + let image_service = Box::new(image_rpc::ImageService::new(s)) + as Box; - let hservice = protocols::health_ttrpc::create_health(health_worker); + let agent_service = protocols::agent_ttrpc::create_agent_service(agent_worker); + + let health_service = protocols::health_ttrpc::create_health(health_worker); + + let image_service = protocols::image_ttrpc::create_image(Arc::new(image_service)); let server = TtrpcServer::new() .bind(server_address) .unwrap() - .register_service(aservice) - .register_service(hservice); + .register_service(agent_service) + .register_service(health_service) + .register_service(image_service); info!(sl!(), "ttRPC server started"; "address" => server_address); @@ -1723,86 +1711,6 @@ fn load_kernel_module(module: &protocols::agent::KernelModule) -> Result<()> { } } -fn pull_image_from_registry(image: &str, cid: &str, source_creds: &Option<&str>) -> Result<()> { - let source_image = format!("{}{}", "docker://", image); - - let manifest_path = format!("/tmp/{}/image_manifest", cid); - let target_path_manifest = format!("dir://{}", manifest_path); - - // Define the target transport and path for the OCI image, without signature - let oci_path = format!("/tmp/{}/image_oci:latest", cid); - let target_path_oci = format!("oci://{}", oci_path); - - fs::create_dir_all(&manifest_path)?; - fs::create_dir_all(&oci_path)?; - - info!(sl!(), "Attempting to pull image {}...", &source_image); - - let mut pull_command = Command::new(SKOPEO_PATH); - pull_command - .arg("--insecure-policy") - .arg("copy") - .arg(source_image) - .arg(&target_path_manifest); - - if let Some(source_creds) = source_creds { - pull_command.arg("--src-creds").arg(source_creds); - } - - let status: ExitStatus = pull_command.status()?; - - if !status.success() { - return Err(anyhow!(format!("failed to pull image: {:?}", status))); - } - - // Copy image from one local file-system to another - // Resulting image is still stored in manifest format, but no longer includes the signature - // The image with a signature can then be unpacked into a bundle - let status: ExitStatus = Command::new(SKOPEO_PATH) - .arg("--insecure-policy") - .arg("copy") - .arg(&target_path_manifest) - .arg(&target_path_oci) - .arg("--remove-signatures") - .status()?; - - if !status.success() { - return Err(anyhow!(format!("failed to copy image: {:?}", status))); - } - - // To save space delete the manifest. - // TODO LATER - when verify image is added, this will need moving the end of that, if required - fs::remove_dir_all(&manifest_path)?; - Ok(()) -} - -fn unpack_image(cid: &str) -> Result<()> { - let source_path_oci = format!("/tmp/{}/image_oci:latest", cid); - let target_path_bundle = format!("{}{}{}", CONTAINER_BASE, "/", cid); - - info!(sl!(), "cid is {:?}", cid); - info!(sl!(), "target_path_bundle is {:?}", target_path_bundle); - - // Unpack image - - let status: ExitStatus = Command::new(UMOCI_PATH) - .arg("--verbose") - .arg("unpack") - .arg("--image") - .arg(&source_path_oci) - .arg(&target_path_bundle) - .status()?; - - if !status.success() { - return Err(anyhow!(format!("failed to unpack image: {:?}", status))); - } - - // To save space delete the oci image after unpack - fs::remove_dir_all(&source_path_oci)?; - - Ok(()) -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/agent/src/sandbox.rs b/src/agent/src/sandbox.rs index ddc18c5c9b..d90bfbafab 100644 --- a/src/agent/src/sandbox.rs +++ b/src/agent/src/sandbox.rs @@ -56,6 +56,7 @@ pub struct Sandbox { pub event_rx: Arc>>, pub event_tx: Option>, pub bind_watcher: BindWatcher, + pub images: HashMap, } impl Sandbox { @@ -88,6 +89,7 @@ impl Sandbox { event_rx, event_tx: Some(tx), bind_watcher: BindWatcher::new(), + images: HashMap::new(), }) } diff --git a/tools/agent-ctl/src/client.rs b/tools/agent-ctl/src/client.rs index 9eb4a9b572..771906ada7 100644 --- a/tools/agent-ctl/src/client.rs +++ b/tools/agent-ctl/src/client.rs @@ -14,6 +14,8 @@ use protocols::agent::*; use protocols::agent_ttrpc::*; use protocols::health::*; use protocols::health_ttrpc::*; +use protocols::image::*; +use protocols::image_ttrpc::*; use slog::{debug, info}; use std::io; use std::io::Write; // XXX: for flush() @@ -45,6 +47,7 @@ type AgentCmdFp = fn( ctx: &Context, client: &AgentServiceClient, health: &HealthClient, + image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()>; @@ -55,6 +58,7 @@ type BuiltinCmdFp = fn(args: &str) -> (Result<()>, bool); enum ServiceType { Agent, Health, + Image, } // XXX: Agent command names *MUST* start with an upper-case letter. @@ -260,7 +264,7 @@ static AGENT_CMDS: &'static [AgentCmd] = &[ }, AgentCmd { name: "PullImage", - st: ServiceType::Agent, + st: ServiceType::Image, fp: agent_cmd_pull_image, }, ]; @@ -316,6 +320,7 @@ fn get_agent_cmd_details() -> Vec { let service = match cmd.st { ServiceType::Agent => "agent", ServiceType::Health => "health", + ServiceType::Image => "image", }; cmds.push(format!("{} ({} service)", cmd.name, service)); @@ -563,6 +568,16 @@ fn kata_service_health( Ok(HealthClient::new(ttrpc_client)) } +fn kata_service_image( + server_address: String, + hybrid_vsock_port: u64, + hybrid_vsock: bool, +) -> Result { + let ttrpc_client = create_ttrpc_client(server_address, hybrid_vsock_port, hybrid_vsock)?; + + Ok(ImageClient::new(ttrpc_client)) +} + fn announce(cfg: &Config) { info!(sl!(), "announce"; "config" => format!("{:?}", cfg)); } @@ -603,6 +618,11 @@ pub fn client(cfg: &Config, commands: Vec<&str>) -> Result<()> { cfg.hybrid_vsock_port, cfg.hybrid_vsock, )?; + let image = kata_service_image( + cfg.server_address.clone(), + cfg.hybrid_vsock_port, + cfg.hybrid_vsock, + )?; let mut options = Options::new(); @@ -620,7 +640,7 @@ pub fn client(cfg: &Config, commands: Vec<&str>) -> Result<()> { "server-address" => cfg.server_address.to_string()); if cfg.interactive { - return interactive_client_loop(&cfg, &mut options, &client, &health, &ttrpc_ctx); + return interactive_client_loop(&cfg, &mut options, &client, &health, &image, &ttrpc_ctx); } let mut repeat_count = 1; @@ -635,6 +655,7 @@ pub fn client(cfg: &Config, commands: Vec<&str>) -> Result<()> { &cfg, &client, &health, + &image, &ttrpc_ctx, repeat_count, &mut options, @@ -660,6 +681,7 @@ fn handle_cmd( cfg: &Config, client: &AgentServiceClient, health: &HealthClient, + image: &ImageClient, ctx: &Context, repeat_count: i64, options: &mut Options, @@ -706,7 +728,7 @@ fn handle_cmd( if first.is_lowercase() { result = handle_builtin_cmd(cmd, &args); } else { - result = handle_agent_cmd(ctx, client, health, options, cmd, &args); + result = handle_agent_cmd(ctx, client, health, image, options, cmd, &args); } if result.0.is_err() { @@ -755,6 +777,7 @@ fn handle_agent_cmd( ctx: &Context, client: &AgentServiceClient, health: &HealthClient, + image: &ImageClient, options: &mut Options, cmd: &str, args: &str, @@ -764,7 +787,7 @@ fn handle_agent_cmd( Err(e) => return (Err(e), false), }; - let result = f(ctx, client, health, options, &args); + let result = f(ctx, client, health, image, options, &args); if result.is_err() { return (result, false); } @@ -779,6 +802,7 @@ fn interactive_client_loop( options: &mut Options, client: &AgentServiceClient, health: &HealthClient, + image: &ImageClient, ctx: &Context, ) -> Result<()> { let result = builtin_cmd_list(""); @@ -801,8 +825,16 @@ fn interactive_client_loop( continue; } - let (result, shutdown) = - handle_cmd(cfg, client, health, ctx, repeat_count, options, &cmdline); + let (result, shutdown) = handle_cmd( + cfg, + client, + health, + image, + ctx, + repeat_count, + options, + &cmdline, + ); if result.is_err() { return result; } @@ -839,6 +871,7 @@ fn agent_cmd_health_check( ctx: &Context, _client: &AgentServiceClient, health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> { @@ -865,6 +898,7 @@ fn agent_cmd_health_version( ctx: &Context, _client: &AgentServiceClient, health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> { @@ -892,6 +926,7 @@ fn agent_cmd_sandbox_create( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -918,6 +953,7 @@ fn agent_cmd_sandbox_destroy( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> { @@ -941,6 +977,7 @@ fn agent_cmd_container_create( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -975,6 +1012,7 @@ fn agent_cmd_container_remove( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1002,6 +1040,7 @@ fn agent_cmd_container_exec( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1048,6 +1087,7 @@ fn agent_cmd_container_stats( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1075,6 +1115,7 @@ fn agent_cmd_container_pause( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1102,6 +1143,7 @@ fn agent_cmd_container_resume( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1129,6 +1171,7 @@ fn agent_cmd_container_start( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1156,6 +1199,7 @@ fn agent_cmd_sandbox_get_guest_details( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> { @@ -1181,6 +1225,7 @@ fn agent_cmd_container_wait_process( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1210,6 +1255,7 @@ fn agent_cmd_container_signal_process( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1249,6 +1295,7 @@ fn agent_cmd_sandbox_tracing_start( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> { @@ -1272,6 +1319,7 @@ fn agent_cmd_sandbox_tracing_stop( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> { @@ -1295,6 +1343,7 @@ fn agent_cmd_sandbox_update_interface( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> { @@ -1320,6 +1369,7 @@ fn agent_cmd_sandbox_update_routes( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> { @@ -1346,6 +1396,7 @@ fn agent_cmd_sandbox_list_interfaces( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> { @@ -1369,6 +1420,7 @@ fn agent_cmd_sandbox_list_routes( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> { @@ -1392,6 +1444,7 @@ fn agent_cmd_container_tty_win_resize( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1440,6 +1493,7 @@ fn agent_cmd_container_close_stdin( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1469,6 +1523,7 @@ fn agent_cmd_container_read_stdout( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1507,6 +1562,7 @@ fn agent_cmd_container_read_stderr( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1545,6 +1601,7 @@ fn agent_cmd_container_write_stdin( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1578,6 +1635,7 @@ fn agent_cmd_sandbox_get_metrics( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> { @@ -1601,6 +1659,7 @@ fn agent_cmd_sandbox_get_oom_event( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> { @@ -1624,6 +1683,7 @@ fn agent_cmd_sandbox_copy_file( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1716,6 +1776,7 @@ fn agent_cmd_sandbox_reseed_random_dev( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1744,6 +1805,7 @@ fn agent_cmd_sandbox_online_cpu_mem( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1797,6 +1859,7 @@ fn agent_cmd_sandbox_set_guest_date_time( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1840,6 +1903,7 @@ fn agent_cmd_sandbox_add_arp_neighbors( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> { @@ -1866,6 +1930,7 @@ fn agent_cmd_sandbox_update_container( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1896,6 +1961,7 @@ fn agent_cmd_sandbox_mem_hotplug_by_probe( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1940,8 +2006,9 @@ fn agent_cmd_sandbox_mem_hotplug_by_probe( fn agent_cmd_pull_image( ctx: &Context, - client: &AgentServiceClient, + _client: &AgentServiceClient, _health: &HealthClient, + image_client: &ImageClient, options: &mut Options, args: &str, ) -> Result<()> { @@ -1959,7 +2026,7 @@ fn agent_cmd_pull_image( debug!(sl!(), "sending request"; "request" => format!("{:?}", req)); - let reply = client + let reply = image_client .pull_image(ctx, &req) .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?; @@ -2038,6 +2105,7 @@ fn agent_cmd_sandbox_add_swap( ctx: &Context, client: &AgentServiceClient, _health: &HealthClient, + _image: &ImageClient, _options: &mut Options, _args: &str, ) -> Result<()> {