summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunitexe <unitexe70@gmail.com>2025-06-07 23:43:27 -0500
committerunitexe <unitexe70@gmail.com>2025-06-07 23:43:27 -0500
commit32f899b71484ee28ce807f998e507719ecbb3541 (patch)
treef44dec7a6ba749abc655074a8dfd54d839cabf9f
parent741a15d4073546628491830d979a34df35ff44e8 (diff)
List container image archives via gRPC server
-rw-r--r--Cargo.lock79
-rw-r--r--Cargo.toml2
-rw-r--r--proto/ormos.proto16
-rw-r--r--src/main.rs75
4 files changed, 171 insertions, 1 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 49138e8..2e1a2fa 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -128,6 +128,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
name = "bytes"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -140,6 +149,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
+name = "cpufeatures"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
+[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -219,6 +257,16 @@ dependencies = [
]
[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
name = "getrandom"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -268,6 +316,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
name = "http"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -679,10 +733,23 @@ dependencies = [
]
[[package]]
+name = "sha2"
+version = "0.10.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
name = "skopos"
version = "0.1.0"
dependencies = [
+ "hex",
"prost",
+ "sha2",
"tokio",
"tonic",
"tonic-build",
@@ -920,12 +987,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
+name = "typenum"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
+
+[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
name = "want"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index c309728..c572423 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,7 +4,9 @@ version = "0.1.0"
edition = "2021"
[dependencies]
+hex = "0.4.3"
prost = "0.13.5"
+sha2 = "0.10.9"
tokio = { version = "1.45.1", features = ["macros", "rt-multi-thread"] }
tonic = "0.13.1"
tonic-reflection = "0.13.1"
diff --git a/proto/ormos.proto b/proto/ormos.proto
index 340dcf5..05ae661 100644
--- a/proto/ormos.proto
+++ b/proto/ormos.proto
@@ -6,6 +6,8 @@ service Ormos {
rpc ListUsbDevices (ListUsbDevicesRequest) returns (ListUsbDevicesResponse) {}
rpc MountUsbDevice (MountUsbDeviceRequest) returns (MountUsbDeviceResponse) {}
rpc UnmountUsbDevice (UnmountUsbDeviceRequest) returns (UnmountUsbDeviceResponse) {}
+
+ rpc ListImageArchives (ListImageArchivesRequest) returns (ListImageArchivesResponse) {}
}
message MountUsbDeviceRequest {
@@ -38,3 +40,17 @@ message UsbDevice {
bool is_mounted = 2;
string mount_point = 3;
}
+
+message ListImageArchivesRequest {
+ string path = 1;
+}
+
+message ListImageArchivesResponse {
+ repeated ImageArchive image_archives = 1;
+}
+
+message ImageArchive {
+ string file_path = 1;
+ int64 file_size_bytes = 2;
+ string sha256_checksum = 3;
+}
diff --git a/src/main.rs b/src/main.rs
index d0bff1c..d55b67a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,9 +1,11 @@
use tonic::{transport::Server, Request, Response, Status};
use skopos::ormos_server::{Ormos, OrmosServer};
-use skopos::{ListUsbDevicesRequest, ListUsbDevicesResponse, UsbDevice, MountUsbDeviceRequest, MountUsbDeviceResponse, UnmountUsbDeviceRequest, UnmountUsbDeviceResponse};
+use skopos::{ListUsbDevicesRequest, ListUsbDevicesResponse, UsbDevice, MountUsbDeviceRequest, MountUsbDeviceResponse, UnmountUsbDeviceRequest, UnmountUsbDeviceResponse, ListImageArchivesRequest, ListImageArchivesResponse, ImageArchive};
use std::io;
use std::fs;
use std::process::Command;
+use std::path::Path;
+use sha2::{Sha256, Digest};
pub mod skopos {
tonic::include_proto!("unit.containers.v0");
@@ -132,6 +134,58 @@ fn unmount_usb_device(mount_point: &str) -> Result<(), io::Error> {
}
}
+fn is_file_a_container_image_archive(path: &Path) -> bool {
+ let output = Command::new("skopeo")
+ .arg("inspect")
+ .arg(format!("docker-archive:{}", path.display()))
+ .output();
+
+ match output {
+ Ok(result) => result.status.success(),
+ Err(_) => false,
+ }
+}
+
+
+fn list_container_image_archives(dir_path: &str) -> std::io::Result<Vec<String>> {
+ let mut images = Vec::new();
+
+ for entry in std::fs::read_dir(dir_path)? {
+ let entry = entry?;
+ let path = entry.path();
+
+ if path.extension().map_or(false, |ext| ext == "tar") {
+ if is_file_a_container_image_archive(&path) {
+ images.push(path.display().to_string());
+ }
+ }
+ }
+
+ Ok(images)
+}
+
+fn create_container_image_archives(archive_paths: Vec<String>) -> Result<Vec<ImageArchive>, Box<dyn std::error::Error>> {
+ archive_paths
+ .into_iter()
+ .map(|archive_path| {
+ let metadata = fs::metadata(&archive_path)?;
+ let archive_size_bytes = metadata.len() as i64;
+
+ let mut file = fs::File::open(&archive_path)?;
+ let mut hasher = Sha256::new();
+ io::copy(&mut file, &mut hasher)?;
+ let hash_bytes = hasher.finalize();
+ let hash_str = hex::encode(hash_bytes);
+
+ Ok(ImageArchive {
+ file_path: archive_path,
+ file_size_bytes: archive_size_bytes,
+ sha256_checksum: hash_str,
+ })
+ })
+ .collect()
+}
+
#[tonic::async_trait]
impl Ormos for MyOrmos {
async fn list_usb_devices(
@@ -208,6 +262,25 @@ impl Ormos for MyOrmos {
}
}
}
+
+ async fn list_image_archives(
+ &self,
+ request: Request<ListImageArchivesRequest>,
+ ) -> Result<Response<ListImageArchivesResponse>, Status> {
+ let req = request.into_inner();
+ let path = if req.path.is_empty() {
+ "/mnt/usb".to_string() // Default mount point
+ } else {
+ req.path
+ };
+ let container_image_archive_paths = list_container_image_archives(&path)?;
+ let image_archives = create_container_image_archives(container_image_archive_paths)
+ .map_err(|e| Status::internal(format!("Failed to create image archive response: {}", e)))?;
+ let response = ListImageArchivesResponse {
+ image_archives,
+ };
+ Ok(Response::new(response))
+ }
}
#[tokio::main]